├── .github └── workflows │ ├── analyze.yml │ └── build.yml ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── NOTICE ├── README.md ├── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src └── java ├── detectors ├── amazon_s3_auto_paginated_with_prefix │ └── AmazonS3AutoPaginatedWithPrefix.java ├── amazon_s3_transfer_manager_shutdown │ └── AmazonS3TransferManagerShutdown.java ├── amazon_sqs_change_message_visibility_check_status │ └── AmazonSqsChangeMessageVisibilityCheckStatus.java ├── amazon_sqs_enable_long_polling │ ├── AmazonSqsEnableLongPollingCompliant.java │ └── AmazonSqsEnableLongPollingNoncompliant.java ├── amazon_sqs_name_url │ ├── AmazonSqsNameUrlCompliant.java │ └── AmazonSqsNameUrlNoncompliant.java ├── avoid_reset_exception_rule │ └── AvoidResetExceptionRule.java ├── aws_bad_params │ └── AwsBadParams.java ├── aws_batch_write_output_ignored │ └── AwsBatchWriteOutputIgnored.java ├── aws_custom_retries │ └── AwsCustomRetries.java ├── aws_dynamodb_getitem_null_check │ └── AwsDynamodbGetitemNullCheck.java ├── aws_dynamodb_mapper_batch_output_ignored │ ├── AwsDynamodbMapperBatchOutputIgnoredCompliant.java │ └── AwsDynamodbMapperBatchOutputIgnoredNoncompliant.java ├── aws_iam_error_prone_policy │ └── AwsIamErrorPronePolicy.java ├── aws_inefficient_chain │ └── AwsInefficientChain.java ├── aws_kms_reencryption │ └── AwsKmsReencryption.java ├── aws_parse_error_message │ └── AwsParseErrorMessage.java ├── aws_region_enumeration │ └── AwsRegionEnumeration.java ├── aws_service_client_initialization │ ├── AwsServiceClientInitializationCompliant.java │ └── AwsServiceClientInitializationNoncompliant.java ├── batches_preferred_over_loops │ └── BatchesPreferredOverLoops.java ├── cipher_update_aad │ └── CipherUpdateAAD.java ├── clear_text_credentials │ └── ClearTextCredentials.java ├── client_constructor_deprecated_rule │ └── ClientConstructorDeprecatedRule.java ├── code_clone │ ├── CodeCloneCompliant.java │ └── CodeCloneNoncompliant.java ├── code_injection │ └── CodeInjection.java ├── concurrency_atomicity_violation │ ├── ConcurrencyAtomicityViolationCompliant.java │ └── ConcurrencyAtomicityViolationNoncompliant.java ├── concurrency_deadlock │ ├── ConcurrencyDeadlockCompliant.java │ └── ConcurrencyDeadlockNoncompliant.java ├── concurrency_over_synchronization │ └── ConcurrencyOverSynchronization.java ├── cross_site_request_forgery │ └── CrossSiteRequestForgery.java ├── cross_site_scripting │ └── CrossSiteScripting.java ├── deprecated_method │ └── DeprecatedMethod.java ├── dynamodb_transaction_library │ ├── DynamodbTransactionLibraryCompliant.java │ └── DynamodbTransactionLibraryNoncompliant.java ├── file_syntax_error │ └── FileSyntaxError.java ├── finalize_on_super_class │ ├── FinalizeOnSuperClassCompliant.java │ └── FinalizeOnSuperClassNoncompliant.java ├── hardcoded_credentials │ └── HardcodedCredentials.java ├── http_response_splitting │ └── HttpResponseSplitting.java ├── improper_locking │ ├── ImproperLockingCompliant.java │ └── ImproperLockingNoncompliant.java ├── incorrect_authentication_exploitation │ └── IncorrectAuthenticationExploitation.java ├── incorrect_null_check_before_setting │ └── IncorrectNullCheckBeforeSetting.java ├── inefficient_apis │ └── InefficientApis.java ├── infinite_loop │ └── InfiniteLoop.java ├── insecure_connection │ └── InsecureConnection.java ├── insecure_cookie │ └── InsecureCookie.java ├── insecure_cors_policy │ └── InsecureCorsPolicy.java ├── insecure_cryptography │ └── InsecureCryptography.java ├── insecure_temporary_file │ └── InsecureTemporaryFile.java ├── iterate_on_map_entries │ └── IterateOnMapEntries.java ├── javax_persistence_id │ ├── JavaxPersistenceIdCompliant.java │ └── JavaxPersistenceIdNoncompliant.java ├── json_parser_length │ └── JsonParserLength.java ├── kcl_with_call_process_records │ └── KclWithCallProcessRecords.java ├── lambda_client_reuse │ ├── LambdaClientReuseCompliant.java │ └── LambdaClientReuseNoncompliant.java ├── lambda_override_reserved │ ├── LambdaOverrideReservedCompliant.java │ └── LambdaOverrideReservedNoncompliant.java ├── ldap_authentication │ └── LdapAuthentication.java ├── ldap_injection │ └── LdapInjection.java ├── log_injection │ └── LogInjection.java ├── loose_file_permissions │ └── LooseFilePermissions.java ├── mandatory_methods │ └── MandatoryMethods.java ├── missing_check_on_android_startactivity │ └── MissingCheckOnAndroidStartActivity.java ├── missing_check_on_createnewfile │ └── MissingCheckOnCreateNewFile.java ├── missing_check_on_method_output │ └── MissingCheckOnMethodOutput.java ├── missing_file_deletion_result_check │ └── MissingFileDeletionResultCheck.java ├── missing_getcause_on_invocationtargetexception │ └── MissingGetCauseOnInvocationTargetException.java ├── missing_position_check_before_substring │ └── MissingPositionCheckBeforeSubstring.java ├── missing_specifically_thrown_exception_handling │ └── MissingSpecificallyThrownExceptionHandling.java ├── missing_timeout_check_on_awaittermination │ └── MissingTimeoutCheckOnAwaitTermination.java ├── missing_timeout_check_on_latch_await │ └── MissingTimeoutCheckOnLatchAwait.java ├── mutually_exclusive_calls_found │ └── MutuallyExclusiveCallsFound.java ├── not_recommended_apis │ └── NotRecommendedApis.java ├── null_check_cache_response_metadata │ └── NullCheckCacheResponseMetadata.java ├── null_pointer_dereference │ └── NullPointerDereference.java ├── object_presence │ └── ObjectPresence.java ├── old_android_features │ └── OldAndroidFeatures.java ├── os_command_injection │ └── OsCommandInjection.java ├── out_of_sync_input_and_output │ └── OutOfSyncInputAndOutput.java ├── output_ignored_on_movetofirst_operation │ └── OutputIgnoredOnMoveToFirstOperation.java ├── partial_encryption │ └── PartialEncryption.java ├── path_traversal │ └── PathTraversal.java ├── reassign_synchronized_object │ └── ReassignSynchronizedObject.java ├── resource_leak │ └── ResourceLeak.java ├── s3_object_metadata_content_length_check │ └── S3ObjectMetadataContentLengthCheck.java ├── s3_object_user_metadata_key_case_sensitivity │ └── S3ObjectUserMetadataKeyCaseSensitivity.java ├── s3_verify_bucket_owner │ └── S3VerifyBucketOwner.java ├── sensitive_information_leak │ └── SensitiveInformationLeak.java ├── session_fixation │ └── SessionFixation.java ├── simple_date_format_time_zone │ └── SimpleDateFormatTimeZone.java ├── simplifiable_code │ └── SimplifiableCode.java ├── sql_injection │ └── SqlInjection.java ├── stream_anymatch_vs_findfirst │ └── StreamAnymatchVsFindfirst.java ├── stream_min_max_vs_sort │ └── StreamMinMaxVsSort.java ├── string_equality_check │ └── StringEqualityCheck.java ├── string_format_arguments │ └── StringFormatArguments.java ├── sudden_service_shutdown │ └── SuddenServiceShutdown.java ├── sync_metric_publish │ ├── SyncMetricPublishCompliant.java │ └── SyncMetricPublishNoncompliant.java ├── thread_safety_class_violations │ ├── ThreadSafetyClassViolationsCompliant.java │ └── ThreadSafetyClassViolationsNoncompliant.java ├── thread_safety_violation │ ├── ThreadSafetyViolationCompliant.java │ └── ThreadSafetyViolationNoncompliant.java ├── throw_exception_with_trace │ └── ThrowExceptionWithTrace.java ├── ui_thread_starvation │ └── UiThreadStarvation.java ├── unspecified_default_value │ └── UnspecifiedDefaultValue.java ├── untrusted_ami_images │ └── UntrustedAmiImages.java ├── untrusted_data_in_decision │ └── UntrustedDataInDecision.java ├── untrusted_deserialization │ └── UntrustedDeserialization.java ├── weak_obfuscation_of_request │ └── WeakObfuscationOfRequest.java ├── weak_random_number_generation │ └── WeakRandomNumberGeneration.java ├── xml_external_entity │ └── XmlExternalEntity.java └── xpath_injection │ └── XpathInjection.java └── stubs ├── ActivityJobItem.java ├── ActivityType.java ├── DynamoBatchWriteOutputCompliant.java ├── DynamoBatchWriteOutputNoncompliant.java ├── DynamoDBMapperCollection.java ├── EC2Client.java ├── FileInfo.java ├── Item.java ├── ResultClass.java ├── ViewHolder.java ├── evaluationJobDao.java ├── finetuningJobDao.java ├── sqsMetricsClient.java └── trainingJobDao.java /.github/workflows/analyze.yml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | # SPDX-License-Identifier: Apache-2.0 4 | # 5 | 6 | name: CodeGuru Reviewer 7 | 8 | on: 9 | # On-demand analysis via "Run workflow" button. 10 | workflow_dispatch: 11 | inputs: 12 | logLevel: 13 | description: 'Log level' 14 | required: true 15 | default: 'debug' 16 | tags: 17 | description: 'Test scenario tags' 18 | # GitHub disables any scheduled analyses by default when you fork a repo. 19 | # Still, please remove these two lines if your fork doesn't need scheduled runs. 20 | schedule: 21 | - cron: '0 0/6 * * *' 22 | 23 | permissions: 24 | id-token: write 25 | contents: read 26 | security-events: write 27 | 28 | jobs: 29 | analyze: 30 | runs-on: ubuntu-latest 31 | steps: 32 | - name: Assume IAM role 33 | id: assume-iam-role 34 | continue-on-error: true 35 | uses: aws-actions/configure-aws-credentials@v1 36 | with: 37 | role-to-assume: arn:aws:iam::048169001733:role/GuruGitHubCICDRole 38 | aws-region: us-west-2 39 | 40 | - name: Check out repository 41 | uses: actions/checkout@v2 42 | if: steps.assume-iam-role.outcome == 'success' 43 | with: 44 | fetch-depth: 0 45 | 46 | - name: Set up JDK 47 | if: steps.assume-iam-role.outcome == 'success' 48 | uses: actions/setup-java@v2 49 | with: 50 | java-version: '8' 51 | distribution: 'adopt' 52 | 53 | - name: Build project with Gradle 54 | if: steps.assume-iam-role.outcome == 'success' 55 | run: | 56 | chmod +x gradlew 57 | ./gradlew build 58 | 59 | - name: Run CodeGuru Reviewer 60 | id: analysis 61 | uses: aws-actions/codeguru-reviewer@v1.1 62 | if: steps.assume-iam-role.outcome == 'success' 63 | continue-on-error: false 64 | with: 65 | s3_bucket: codeguru-reviewer-github-profiler-demo-048169001733-uw2 66 | build_path: ./build/libs 67 | 68 | - name: Upload SARIF file to workflow artifacts 69 | if: steps.assume-iam-role.outcome == 'success' && steps.analysis.outcome == 'success' 70 | uses: actions/upload-artifact@v2 71 | with: 72 | name: codeguru-results.sarif.json 73 | path: codeguru-results.sarif.json 74 | 75 | # 76 | # Upload the SARIF analysis results to GitHub so that they appear on the GitHub UX. 77 | # 78 | # Note: This step will fail if your GitHub repo is private (unless you buy GitHub Advanced Security). 79 | # 80 | 81 | - name: Upload SARIF file to GitHub Security Scans UX 82 | if: steps.assume-iam-role.outcome == 'success' && steps.analysis.outcome == 'success' 83 | uses: github/codeql-action/upload-sarif@v2 84 | with: 85 | sarif_file: codeguru-results.sarif.json 86 | 87 | # 88 | # The following steps are optional. 89 | # 90 | # Create a sorted summary of recommendations in CSV format (detector,filePath,lineNumber). 91 | # We do this because analyzing this repo (by design) produces lots of recommendations! 92 | # 93 | # This summary omits most of the useful information in the full results: recommendation text, 94 | # mitigations, "Learn more" links, etcetera. But its compact format (one line per finding) 95 | # makes it useful as an overview, and to compute diffs between two analysis runs. 96 | # 97 | 98 | - name: Save a summary of the results to a file on local disk 99 | if: steps.assume-iam-role.outcome == 'success' && steps.analysis.outcome == 'success' 100 | run: | 101 | echo "detector,filePath,lineNumber" > summary-of-results.csv 102 | jq -r '.runs[0].results[] | {ruleId: .ruleId, firstFile: .locations[0].physicalLocation.artifactLocation.uri, firstLine: .locations[0].physicalLocation.region.startLine} | join(",")' \ 103 | codeguru-results.sarif.json | sort >> summary-of-results.csv 104 | 105 | - name: Upload results summary to workflow artifacts 106 | if: steps.assume-iam-role.outcome == 'success' && steps.analysis.outcome == 'success' 107 | uses: actions/upload-artifact@v2 108 | with: 109 | name: summary-of-results.csv 110 | path: summary-of-results.csv 111 | 112 | - name: Print CSV summary of analysis results to the action log 113 | if: steps.assume-iam-role.outcome == 'success' && steps.analysis.outcome == 'success' 114 | run: cat summary-of-results.csv 115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | # SPDX-License-Identifier: Apache-2.0 4 | # 5 | 6 | name: Build (Gradle) 7 | 8 | on: 9 | push: 10 | branches: [ main ] 11 | pull_request: 12 | branches: [ main ] 13 | 14 | jobs: 15 | build: 16 | 17 | runs-on: ${{ matrix.os }} 18 | strategy: 19 | matrix: 20 | os: [ ubuntu-latest, windows-latest, macos-latest ] 21 | 22 | steps: 23 | - run: echo "The job was automatically triggered by a ${{ github.event_name }} event." 24 | - run: echo "This job is now running on a ${{ runner.os }} server hosted by GitHub!" 25 | - run: echo "The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}." 26 | - name: Check out repository code 27 | uses: actions/checkout@v2 28 | - name: Set up JDK 29 | uses: actions/setup-java@v2 30 | with: 31 | java-version: '17' 32 | distribution: 'adopt' 33 | - name: Grant execute permission for gradlew 34 | run: chmod +x gradlew 35 | - name: Build with Gradle 36 | run: ./gradlew build 37 | - run: echo "This job's status is ${{ job.status }}." -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com, Inc. and its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | # Gradle 5 | .gradle/ 6 | 7 | # IntelliJ 8 | /.idea/ 9 | *.iml 10 | 11 | build/ 12 | lib/ 13 | .DS_Store 14 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 4 | opensource-codeofconduct@amazon.com with any additional questions or comments. 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional 4 | documentation, we greatly value feedback and contributions from our community. 5 | 6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary 7 | information to effectively respond to your bug report or contribution. 8 | 9 | 10 | ## Reporting Bugs/Feature Requests 11 | 12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features. 13 | 14 | When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already 15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: 16 | 17 | * A reproducible test case or series of steps 18 | * The version of our code being used 19 | * Any modifications you've made relevant to the bug 20 | * Anything unusual about your environment or deployment 21 | 22 | 23 | ## Contributing via Pull Requests 24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 25 | 26 | 1. You are working against the latest source on the *main* branch. 27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted. 29 | 30 | To send us a pull request, please: 31 | 32 | 1. Fork the repository. 33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. 34 | 3. Ensure local tests pass. 35 | 4. Commit to your fork using clear commit messages. 36 | 5. Send us a pull request, answering any default questions in the pull request interface. 37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. 38 | 39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and 40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). 41 | 42 | 43 | ## Finding contributions to work on 44 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' issues is a great place to start. 45 | 46 | 47 | ## Code of Conduct 48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 50 | opensource-codeofconduct@amazon.com with any additional questions or comments. 51 | 52 | 53 | ## Security issue notifications 54 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. 55 | 56 | 57 | ## Licensing 58 | 59 | See the [LICENSE](LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. 60 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | amazon-codeguru-reviewer-java-detectors 2 | Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Amazon CodeGuru Reviewer Java Detector Examples 2 | 3 | Amazon CodeGuru Reviewer is an AWS service that uses program analysis and machine learning to detect potential defects that are difficult for developers to find and offers suggestions for improvement. 4 | 5 | CodeGuru Reviewer finds defects in Java and Python code. For more information about how to set up and use CodeGuru Reviewer, see the [Amazon CodeGuru Reviewer User Guide](https://docs.aws.amazon.com/codeguru/latest/reviewer-ug/welcome.html). 6 | 7 | This repo demonstrates some of CodeGuru Reviewer's Java detectors. For more descriptions of each detector, see our [Detector Library](https://docs.aws.amazon.com/codeguru/detector-library/index.html). To see the Python code examples repo, click [here](https://github.com/aws-samples/amazon-codeguru-reviewer-python-detectors). 8 | 9 | ## Try out the CodeGuru Reviewer GitHub Action on this repo 10 | 11 | You can use this code repository to try out CodeGuru Reviewer using your AWS credentials. 12 | 13 | ### Prerequisites 14 | 15 | To use the CodeGuru Reviewer GitHub Action to scan a fork of this repo, you will first need to create a suitable Role, S3 Bucket, and Policy in your AWS account. You can do this automatically by following [these instructions](https://github.com/aws-samples/aws-codeguru-reviewer-cicd-cdk-sample#cdk-typescript-project-to-set-up-the-codeguru-reviewer-cicd-integration). 16 | 17 | ### Setup 18 | A CodeGuru Reviewer GitHub Action workflow template has already been added to this repo. To see CodeGuru Reviewer in action: 19 | 20 | 1. Fork this repo. 21 | 2. In `.github/workflows/analyze.yml`, replace the following three fields with the values obtained from the prerequisites step above: your Role ARN (`role-to-assume`), your Region (`aws-region`), and your S3 bucket name (`s3_bucket`). 22 | 3. Click on the Actions tab (next to pull requests). 23 | 4. Click on the CodeGuru Reviewer Workflow. 24 | 5. Click "Run workflow". 25 | 6. Navigate to the Security tab to see results (it should take 5-10 min). GitHub only enables the security tab for free on public repositories. 26 | 27 | ## Try out the CodeGuru Reviewer GitHub Action on your own repo 28 | 29 | You can copy the CodeGuru Reviewer GitHub Action `analyze.yml` that you made in the Setup step to your own personal repo. However, please take note of the following items: 30 | 31 | - If you use a build system other than Gradle, you may need to edit the build step using the appropriate command for your build system. 32 | - If your build system doesn't place the resulting .jar files in `build/libs`, you may need to edit the `build_path` field in the `analyze.yml` workflow. 33 | - If you do not have GitHub Advanced Security, you will still be able to view your findings within the AWS Console. You can also use tools like `jq` within your workflow to postprocess the findings. If you print some of the findings to `stdout`, you will see them in your workflow's output log. 34 | 35 | ## Getting Help 36 | 37 | Use the community resources below for getting help with AWS CodeGuru Reviewer. 38 | 39 | - Use GitHub issues to report bugs and request features. 40 | - Open a support ticket with [AWS Support](https://docs.aws.amazon.com/awssupport/latest/user/getting-started.html). 41 | - For contributing guidelines, refer to [CONTRIBUTING](https://github.com/aws-samples/amazon-codeguru-reviewer-python-detectors/blob/main/CONTRIBUTING.md). 42 | 43 | ## Contributing 44 | 45 | See [CONTRIBUTING](CONTRIBUTING.md#security-issue-notifications) for more information. 46 | 47 | ## License 48 | 49 | This project is licensed under the Apache-2.0 License. See the [LICENSE](LICENSE) file. 50 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | plugins { 5 | id 'java' 6 | id "io.freefair.lombok" version "6.3.0" 7 | } 8 | 9 | group 'org.example' 10 | version '1.0-SNAPSHOT' 11 | 12 | repositories { 13 | mavenCentral() 14 | google() 15 | } 16 | 17 | sourceSets { 18 | main { 19 | java { 20 | srcDir 'src/java' 21 | exclude 'detectors/file_syntax_error/FileSyntaxError.java', 22 | 'detectors/dynamodb_transaction_library/DynamodbTransactionLibraryNoncompliant.java' 23 | } 24 | } 25 | } 26 | 27 | dependencies { 28 | implementation("javax.servlet:javax.servlet-api:4.0.1") 29 | implementation("org.apache.httpcomponents:httpclient:4.5.13") 30 | implementation("org.slf4j:slf4j-api:1.7.32") 31 | implementation("org.opensaml:xmltooling:1.4.4") 32 | implementation("com.amazonaws:aws-lambda-java-core:1.0.0") 33 | implementation("com.amazonaws:aws-java-sdk-datapipeline:1.12.131") 34 | implementation("com.amazonaws:aws-java-sdk-sqs:1.12.132") 35 | implementation("com.amazonaws:aws-java-sdk-iam:1.12.132") 36 | implementation("com.amazonaws:aws-java-sdk-ec2:1.12.132") 37 | implementation("com.amazonaws:aws-java-sdk-s3:1.12.132") 38 | implementation("software.amazon.awssdk:s3:2.17.103") 39 | implementation("software.amazon.awssdk:kms:2.17.102") 40 | implementation("software.amazon.kinesis:amazon-kinesis-client:2.3.10") 41 | implementation("com.amazonaws:amazon-kinesis-client:1.6.3") 42 | implementation("com.amazonaws:aws-java-sdk-ssm:1.11.201") 43 | implementation("io.netty:netty-all:4.1.72.Final") 44 | implementation("io.grpc:grpc-netty:1.44.0") 45 | implementation("org.springframework.security:spring-security-config:5.6.1") 46 | implementation("org.springframework:spring-web:5.3.14") 47 | implementation("org.springframework:spring-webmvc:5.3.14") 48 | implementation("org.apache.hivemall:hivemall-core:0.6.0-incubating") 49 | implementation("com.fasterxml.jackson.core:jackson-core:2.13.1") 50 | implementation("org.apache.hadoop:hadoop-common:3.3.1") 51 | implementation("com.amazonaws:aws-java-sdk-kinesis:1.12.131") 52 | implementation("com.amazonaws:aws-java-sdk-lambda:1.12.131") 53 | implementation("com.amazonaws:aws-java-sdk-cloudwatch:1.12.131") 54 | implementation("com.amazonaws:aws-lambda-java-events:3.11.0") 55 | implementation("javax.persistence:javax.persistence-api:2.2") 56 | implementation("com.amazonaws:aws-java-sdk:1.12.131") 57 | implementation("com.android.support:support-annotations:27.1.1") 58 | implementation("com.google.code.findbugs:jsr305:3.0.2") 59 | implementation("com.amazonaws:aws-java-sdk-dynamodb:1.12.133") 60 | implementation("com.google.android:android:4.1.1.4") 61 | } 62 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/amazon-codeguru-java-detectors/f8808bf4c319a2287b708c434e88e358af82a6a9/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | rootProject.name = 'amazon-codeguru-reviewer-java-detectors' 5 | -------------------------------------------------------------------------------- /src/java/detectors/amazon_s3_auto_paginated_with_prefix/AmazonS3AutoPaginatedWithPrefix.java: -------------------------------------------------------------------------------- 1 | package detectors.amazon_s3_auto_paginated_with_prefix; 2 | 3 | import com.amazonaws.services.s3.AmazonS3; 4 | import com.amazonaws.services.s3.iterable.S3Objects; 5 | import com.amazonaws.services.s3.model.ListObjectsV2Request; 6 | import com.amazonaws.services.s3.model.ListObjectsV2Result; 7 | import com.amazonaws.services.s3.model.S3ObjectSummary; 8 | 9 | public class AmazonS3AutoPaginatedWithPrefix { 10 | 11 | // {fact rule=amazon-s3-auto-paginated-with-prefix@v1.0 defects=1} 12 | public void s3GetObjectsNoncompliant(AmazonS3 amazonS3Client, String bucketName) { 13 | String continuationToken = null; 14 | ListObjectsV2Request listObjectsV2Request = new ListObjectsV2Request().withBucketName(bucketName); 15 | ListObjectsV2Result listObjectsV2Result; 16 | do { 17 | // Noncompliant: uses manual pagination. 18 | listObjectsV2Result = amazonS3Client.listObjectsV2(listObjectsV2Request); 19 | for (S3ObjectSummary objectSummary : listObjectsV2Result.getObjectSummaries()) { 20 | System.out.printf(" - %s (size: %d)\n", objectSummary.getKey(), objectSummary.getSize()); 21 | } 22 | continuationToken = listObjectsV2Result.getNextContinuationToken(); 23 | listObjectsV2Request.setContinuationToken(continuationToken); 24 | } while (continuationToken != null); 25 | } 26 | // {/fact} 27 | 28 | // {fact rule=amazon-s3-auto-paginated-with-prefix@v1.0 defects=0} 29 | public void s3GetObjectsCompliant(AmazonS3 amazonS3Client, String bucketName, String prefix) { 30 | // Compliant: uses S3Objects.withPrefix() for pagination. 31 | for (S3ObjectSummary objectSummary : S3Objects.withPrefix(amazonS3Client, bucketName, prefix)) { 32 | System.out.printf(" - %s (size: %d)\n", objectSummary.getKey(), objectSummary.getSize()); 33 | } 34 | } 35 | // {/fact} 36 | } 37 | -------------------------------------------------------------------------------- /src/java/detectors/amazon_s3_transfer_manager_shutdown/AmazonS3TransferManagerShutdown.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.amazon_s3_transfer_manager_shutdown; 7 | 8 | import com.amazonaws.services.s3.model.PutObjectRequest; 9 | import com.amazonaws.services.s3.transfer.TransferManager; 10 | import com.amazonaws.services.s3.transfer.TransferManagerBuilder; 11 | import com.amazonaws.services.s3.transfer.Upload; 12 | 13 | public class AmazonS3TransferManagerShutdown { 14 | 15 | // {fact rule=amazon-s3-transfer-manager-shutdown@v1.0 defects=1} 16 | public void transferManagerNoncompliant(PutObjectRequest putRequest) { 17 | // Noncompliant: transferManager is not shutdown. 18 | TransferManager transferManager = TransferManagerBuilder.defaultTransferManager(); 19 | try { 20 | final Upload upload = transferManager.upload(putRequest); 21 | upload.waitForCompletion(); 22 | } 23 | catch (InterruptedException e) { 24 | Thread.currentThread().interrupt(); 25 | } 26 | } 27 | // {/fact} 28 | 29 | // {fact rule=amazon-s3-transfer-manager-shutdown@v1.0 defects=0} 30 | public void transferManagerCompliant(PutObjectRequest putRequest) { 31 | TransferManager transferManager = TransferManagerBuilder.defaultTransferManager(); 32 | try { 33 | final Upload upload = transferManager.upload(putRequest); 34 | upload.waitForCompletion(); 35 | } 36 | catch (InterruptedException e) { 37 | Thread.currentThread().interrupt(); 38 | } finally 39 | { 40 | // Compliant: transferManager is shutdown. 41 | transferManager.shutdownNow(); 42 | } 43 | } 44 | // {/fact} 45 | } 46 | -------------------------------------------------------------------------------- /src/java/detectors/amazon_sqs_change_message_visibility_check_status/AmazonSqsChangeMessageVisibilityCheckStatus.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.amazon_sqs_change_message_visibility_check_status; 7 | 8 | import com.amazonaws.services.sqs.AmazonSQS; 9 | import com.amazonaws.services.sqs.model.ChangeMessageVisibilityRequest; 10 | import com.amazonaws.services.sqs.model.MessageNotInflightException; 11 | import lombok.extern.slf4j.Slf4j; 12 | 13 | import static java.lang.String.format; 14 | 15 | @Slf4j 16 | public class AmazonSqsChangeMessageVisibilityCheckStatus { 17 | 18 | // {fact rule=amazon-sqs-change-message-visibility-check-status@v1.0 defects=1} 19 | public void changeSqsMessageVisibilityNoncompliant(AmazonSQS amazonSqsClient, ChangeMessageVisibilityRequest request) { 20 | // Noncompliant: MessageNotInFlight exception is not checked when changing message visibility. 21 | amazonSqsClient.changeMessageVisibility(request); 22 | } 23 | // {/fact} 24 | 25 | // {fact rule=amazon-sqs-change-message-visibility-check-status@v1.0 defects=0} 26 | public void changeSqsMessageVisibilityCompliant(AmazonSQS amazonSqsClient, ChangeMessageVisibilityRequest request) { 27 | // Compliant: MessageNotInFlight exception is checked when changing message visibility. 28 | try { 29 | amazonSqsClient.changeMessageVisibility(request); 30 | } catch (MessageNotInflightException ex) { 31 | log.info(format("Message with receipt handle %s already visible. Too late to abandon", request.getReceiptHandle())); 32 | } catch (Exception ex) { 33 | log.error(format("Caught unknown exception %s", request.getReceiptHandle()), ex); 34 | } 35 | } 36 | // {/fact} 37 | } 38 | -------------------------------------------------------------------------------- /src/java/detectors/amazon_sqs_enable_long_polling/AmazonSqsEnableLongPollingCompliant.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.amazon_sqs_enable_long_polling; 7 | 8 | import com.amazonaws.services.sqs.AmazonSQS; 9 | import com.amazonaws.services.sqs.AmazonSQSClientBuilder; 10 | import com.amazonaws.services.sqs.model.CreateQueueRequest; 11 | import com.amazonaws.services.sqs.model.CreateQueueResult; 12 | import com.amazonaws.services.sqs.model.QueueDeletedRecentlyException; 13 | import com.amazonaws.services.sqs.model.QueueNameExistsException; 14 | import com.amazonaws.services.sqs.model.ReceiveMessageRequest; 15 | import java.util.HashMap; 16 | import java.util.Map; 17 | 18 | // {fact rule=amazon-sqs-enable-long-polling@v1.0 defects=0} 19 | public class AmazonSqsEnableLongPollingCompliant { 20 | 21 | public static void main(String[] args) { 22 | 23 | final AmazonSQS sqs = AmazonSQSClientBuilder.defaultClient(); 24 | String queueNamePattern = "sqs-poc-fifo-queue"; 25 | int numOfQueues = 6; 26 | String queue_url="QUEUE_URL"; 27 | createQueues(sqs, queueNamePattern, numOfQueues, queue_url); 28 | } 29 | 30 | /** 31 | * Create FIFO queues based on the Queue Name pattern and the number of queues 32 | * needed 33 | * 34 | * @param sqs 35 | * @param queueNamePattern 36 | * @param numOfQueues 37 | */ 38 | public static void createQueues(AmazonSQS sqs, 39 | String queueNamePattern, 40 | int numOfQueues, 41 | String queue_url) { 42 | 43 | Map attributes = new HashMap(); 44 | attributes.put("FifoQueue", "true"); 45 | attributes.put("ContentBasedDeduplication", "true"); 46 | attributes.put("DelaySeconds", "0"); 47 | attributes.put("MessageRetentionPeriod", "86400"); // this is 24 shours 48 | attributes.put("ReceiveMessageWaitTimeSeconds", "20"); // enables long polling 49 | 50 | for (int i = 1; i < numOfQueues + 1; i++) { 51 | String queueName = queueNamePattern + "-" + i + ".fifo"; 52 | // Compliant: enables long polling for efficiency. 53 | CreateQueueRequest createQueueRequest = new CreateQueueRequest(queueName).withAttributes(attributes); 54 | try { 55 | CreateQueueResult res = sqs.createQueue(createQueueRequest); 56 | System.out.println("SQS Queue created, queue url: " + res.getQueueUrl()); 57 | } catch (QueueNameExistsException e) { 58 | System.out.println("A queue with name " + queueName 59 | + " already exist. Renaming it with _v1 suffix before next attempt"); 60 | queueName = queueNamePattern + "-" + i + "-v1" + "-src.fifo"; 61 | createQueueRequest = new CreateQueueRequest(queueName).withAttributes(attributes); 62 | sqs.createQueue(createQueueRequest); 63 | 64 | } catch (QueueDeletedRecentlyException e) { 65 | try { 66 | System.out.println(e.getMessage()); 67 | System.out.println("Queue recently deleted. Sleeping for 65 seconds before recreating the queue"); 68 | Thread.sleep(65000); 69 | createQueueRequest = new CreateQueueRequest(queueName).withAttributes(attributes); 70 | sqs.createQueue(createQueueRequest); 71 | 72 | } catch (InterruptedException e1) { 73 | e1.printStackTrace(); 74 | } 75 | } 76 | ReceiveMessageRequest receive_request = new ReceiveMessageRequest() 77 | .withQueueUrl(queue_url); 78 | sqs.receiveMessage(receive_request); 79 | 80 | } 81 | 82 | } 83 | } 84 | // {/fact} 85 | -------------------------------------------------------------------------------- /src/java/detectors/amazon_sqs_enable_long_polling/AmazonSqsEnableLongPollingNoncompliant.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.amazon_sqs_enable_long_polling; 7 | 8 | import com.amazonaws.services.sqs.AmazonSQS; 9 | import com.amazonaws.services.sqs.AmazonSQSClientBuilder; 10 | import com.amazonaws.services.sqs.model.CreateQueueRequest; 11 | import com.amazonaws.services.sqs.model.CreateQueueResult; 12 | import com.amazonaws.services.sqs.model.QueueNameExistsException; 13 | import com.amazonaws.services.sqs.model.QueueDeletedRecentlyException; 14 | import com.amazonaws.services.sqs.model.ReceiveMessageRequest; 15 | import java.util.HashMap; 16 | import java.util.Map; 17 | 18 | // {fact rule=amazon-sqs-enable-long-polling@v1.0 defects=1} 19 | public class AmazonSqsEnableLongPollingNoncompliant { 20 | 21 | public static void main(String[] args) { 22 | 23 | final AmazonSQS sqs = AmazonSQSClientBuilder.defaultClient(); 24 | String queueNamePattern = "sqs-poc-fifo-queue"; 25 | int numOfQueues = 6; 26 | String queue_url="QUEUE_URL"; 27 | createQueuesNoncompliant(sqs, queueNamePattern, numOfQueues, queue_url); 28 | } 29 | 30 | /** 31 | * Create FIFO queues based on the Queue Name pattern and the number of queues 32 | * needed 33 | * 34 | * @param sqs 35 | * @param queueNamePattern 36 | * @param numOfQueues 37 | */ 38 | public static void createQueuesNoncompliant(AmazonSQS sqs, 39 | String queueNamePattern, 40 | int numOfQueues, 41 | String queue_url) { 42 | 43 | Map attributes = new HashMap(); 44 | attributes.put("FifoQueue", "true"); 45 | attributes.put("ContentBasedDeduplication", "true"); 46 | attributes.put("DelaySeconds", "0"); 47 | attributes.put("MessageRetentionPeriod", "86400"); // this is 24 shours 48 | 49 | for (int i = 1; i < numOfQueues + 1; i++) { 50 | String queueName = queueNamePattern + "-" + i + ".fifo"; 51 | // Noncompliant: avoids enabling long polling. 52 | CreateQueueRequest createQueueRequest = new CreateQueueRequest(queueName).withAttributes(attributes); 53 | try { 54 | CreateQueueResult res = sqs.createQueue(createQueueRequest); 55 | System.out.println("SQS Queue created, queue url: " + res.getQueueUrl()); 56 | } catch (QueueNameExistsException e) { 57 | System.out.println("A queue with name " + queueName 58 | + " already exist. Renaming it with _v1 suffix before next attempt"); 59 | queueName = queueNamePattern + "-" + i + "-v1" + "-src.fifo"; 60 | createQueueRequest = new CreateQueueRequest(queueName).withAttributes(attributes); 61 | sqs.createQueue(createQueueRequest); 62 | 63 | } catch (QueueDeletedRecentlyException e) { 64 | try { 65 | System.out.println(e.getMessage()); 66 | System.out.println("Queue recently deleted. Sleeping for 65 seconds before recreating the queue"); 67 | Thread.sleep(65000); 68 | createQueueRequest = new CreateQueueRequest(queueName).withAttributes(attributes); 69 | sqs.createQueue(createQueueRequest); 70 | 71 | } catch (InterruptedException e1) { 72 | e1.printStackTrace(); 73 | } 74 | } 75 | ReceiveMessageRequest receive_request = new ReceiveMessageRequest() 76 | .withQueueUrl(queue_url); 77 | sqs.receiveMessage(receive_request); 78 | 79 | } 80 | 81 | } 82 | } 83 | // {/fact} 84 | -------------------------------------------------------------------------------- /src/java/detectors/amazon_sqs_name_url/AmazonSqsNameUrlCompliant.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.amazon_sqs_name_url; 7 | 8 | import com.amazonaws.services.sqs.model.Message; 9 | import stubs.sqsMetricsClient; 10 | import java.util.concurrent.Callable; 11 | 12 | // {fact rule=amazon-sqs-name-url@v1.0 defects=0} 13 | public abstract class AmazonSqsNameUrlCompliant implements Callable { 14 | 15 | public void compliant() { 16 | final String queueUrl = "queueUrl"; 17 | // Compliant: queue URL passed to SQS instead of queue name. 18 | sqsMetricsClient.changeMessageVisibility(queueUrl, "ReceiptHandle", "VisibilityTimeout"); 19 | } 20 | } 21 | // {/fact} 22 | -------------------------------------------------------------------------------- /src/java/detectors/amazon_sqs_name_url/AmazonSqsNameUrlNoncompliant.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.amazon_sqs_name_url; 7 | 8 | import com.amazonaws.services.sqs.model.Message; 9 | import stubs.sqsMetricsClient; 10 | 11 | import java.util.concurrent.Callable; 12 | 13 | // {fact rule=amazon-sqs-name-url@v1.0 defects=1} 14 | public abstract class AmazonSqsNameUrlNoncompliant implements Callable { 15 | 16 | public void non_compliant() { 17 | final String queueName = "queueName"; 18 | // Noncompliant: queue name passed to SQS instead of queue URL. 19 | sqsMetricsClient.changeMessageVisibility(queueName, "ReceiptHandle", "VisibilityTimeout"); 20 | } 21 | } 22 | // {/fact} 23 | -------------------------------------------------------------------------------- /src/java/detectors/avoid_reset_exception_rule/AvoidResetExceptionRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.avoid_reset_exception_rule; 7 | 8 | import com.amazonaws.services.s3.AmazonS3; 9 | import com.amazonaws.services.s3.model.ObjectMetadata; 10 | import com.amazonaws.services.s3.model.PutObjectRequest; 11 | import lombok.extern.slf4j.Slf4j; 12 | import java.io.InputStream; 13 | 14 | @Slf4j 15 | public class AvoidResetExceptionRule { 16 | 17 | // {fact rule=avoid-reset-exception-rule@v1.0 defects=1} 18 | public void s3PutObjectNoncompliant(String bucket, String key, InputStream content, 19 | ObjectMetadata metadata, AmazonS3 s3Client, String owner) { 20 | log.info("Putting content into bucket {} and key {}", bucket, key); 21 | // Noncompliant: readLimit not set. 22 | PutObjectRequest putObjectRequest = new PutObjectRequest(bucket, key, content, metadata); 23 | putObjectRequest.setExpectedBucketOwner(owner); 24 | s3Client.putObject(putObjectRequest); 25 | } 26 | // {/fact} 27 | 28 | // {fact rule=avoid-reset-exception-rule@v1.0 defects=0} 29 | public void s3PutObjectCompliant(String bucket, String key, InputStream content, 30 | ObjectMetadata metadata, AmazonS3 s3Client, String owner) { 31 | log.info("Putting content into bucket {} and key {}", bucket, key); 32 | PutObjectRequest putObjectRequest = new PutObjectRequest(bucket, key, content, metadata); 33 | putObjectRequest.setExpectedBucketOwner(owner); 34 | // Compliant: readLimit is set. 35 | putObjectRequest.getRequestClientOptions().setReadLimit(100); 36 | s3Client.putObject(putObjectRequest); 37 | } 38 | // {/fact} 39 | } 40 | -------------------------------------------------------------------------------- /src/java/detectors/aws_bad_params/AwsBadParams.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.aws_bad_params; 7 | 8 | import com.amazonaws.services.elasticmapreduce.model.ActionOnFailure; 9 | import com.amazonaws.services.elasticmapreduce.model.StepConfig; 10 | 11 | public class AwsBadParams { 12 | 13 | // {fact rule=aws-bad-params@v1.0 defects=1} 14 | public void createStepConfigNoncompliant() { 15 | // Noncompliant: ActionOnFailure.TERMINATE_JOB_FLOW is outdated. 16 | new StepConfig().withName("sampleStepName").withActionOnFailure(ActionOnFailure.TERMINATE_JOB_FLOW); 17 | } 18 | // {/fact} 19 | 20 | // {fact rule=aws-bad-params@v1.0 defects=0} 21 | public void createStepConfigCompliant() { 22 | // Compliant: ActionOnFailure.TERMINATE_CLUSTER is used. 23 | new StepConfig().withName("sampleStepName").withActionOnFailure(ActionOnFailure.TERMINATE_CLUSTER); 24 | } 25 | // {/fact} 26 | } 27 | -------------------------------------------------------------------------------- /src/java/detectors/aws_batch_write_output_ignored/AwsBatchWriteOutputIgnored.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.aws_batch_write_output_ignored; 7 | 8 | import com.amazonaws.services.sqs.model.BatchResultErrorEntry; 9 | import com.amazonaws.services.sqs.model.SendMessageBatchRequestEntry; 10 | import com.amazonaws.services.sqs.model.SendMessageBatchResult; 11 | import java.util.List; 12 | import java.util.stream.Collectors; 13 | 14 | public class AwsBatchWriteOutputIgnored { 15 | 16 | // {fact rule=aws-batch-write-output-ignored@v1.0 defects=1} 17 | public void flushNoncompliant(final SqsClient amazonSqs, 18 | final String sqsEndPoint, 19 | final List batch) 20 | throws CloneNotSupportedException { 21 | if (batch.isEmpty()) { 22 | return; 23 | } 24 | SendMessageBatchResult sendResult = 25 | amazonSqs.sendMessageBatch(sqsEndPoint, batch); 26 | // Noncompliant: no checks to handle errors returned by batch operations. 27 | batch.clear(); 28 | } 29 | 30 | // {/fact} 31 | 32 | // {fact rule=aws-batch-write-output-ignored@v1.0 defects=0} 33 | public void flushCompliant(final SqsClient amazonSqs, 34 | final String sqsEndPoint, 35 | final List batch) 36 | throws SQSUpdateException, CloneNotSupportedException { 37 | if (batch.isEmpty() || sqsEndPoint == null) { 38 | return; 39 | } 40 | SendMessageBatchResult sendResult = 41 | amazonSqs.sendMessageBatch(sqsEndPoint, batch); 42 | if (sendResult == null) { 43 | return; 44 | } else { 45 | final List failed = sendResult.getFailed(); 46 | // Compliant: has checks to handle errors returned by batch operations. 47 | if (!failed.isEmpty()) { 48 | final String failedMessage = failed.stream() 49 | .map(batchResultErrorEntry -> String.format("messageId:%s failedReason:%s", 50 | batchResultErrorEntry.getId(), batchResultErrorEntry.getMessage())) 51 | .collect(Collectors.joining(",")); 52 | throw new SQSUpdateException("Error occurred while sending messages to SQS::" + failedMessage); 53 | } 54 | } 55 | } 56 | // {/fact} 57 | 58 | public class SqsClient { 59 | public SendMessageBatchResult sendMessageBatch(String sqsEndPoint, List batch) 60 | throws CloneNotSupportedException { 61 | SendMessageBatchResult result = (SendMessageBatchResult) clone(); 62 | return result; 63 | } 64 | } 65 | 66 | private class SQSUpdateException extends Throwable { 67 | public SQSUpdateException(String s) { 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/java/detectors/aws_custom_retries/AwsCustomRetries.java: -------------------------------------------------------------------------------- 1 | package detectors.aws_custom_retries; 2 | 3 | import com.amazonaws.AmazonServiceException; 4 | import com.amazonaws.ClientConfiguration; 5 | import com.amazonaws.retry.RetryPolicy; 6 | import com.amazonaws.services.lambda.AWSLambda; 7 | import com.amazonaws.services.lambda.AWSLambdaClientBuilder; 8 | import com.amazonaws.services.lambda.model.InvokeRequest; 9 | import com.amazonaws.services.lambda.model.InvokeResult; 10 | import lombok.extern.slf4j.Slf4j; 11 | 12 | @Slf4j 13 | public class AwsCustomRetries { 14 | 15 | // {fact rule=aws-custom-retries@v1.0 defects=1} 16 | public InvokeResult invokeLambdaNoncompliant() { 17 | AWSLambda awsLambdaClient = AWSLambdaClientBuilder.standard().build(); 18 | final InvokeRequest request = new InvokeRequest(); 19 | // Noncompliant: manual retry if a service exception is thrown. 20 | for(int i=0; i <= 5; i++) { 21 | try { 22 | return awsLambdaClient.invoke(request); 23 | } catch (AmazonServiceException e) { 24 | log.error("Exception: " + e); 25 | } 26 | } 27 | return null; 28 | } 29 | // {/fact} 30 | 31 | // {fact rule=aws-custom-retries@v1.0 defects=0} 32 | public InvokeResult invokeLambdaCompliant() { 33 | // Compliant: uses retry policy. 34 | ClientConfiguration clientConfiguration = new ClientConfiguration() 35 | .withRetryPolicy(RetryPolicy.builder() 36 | .withMaxErrorRetry(5) 37 | .build()); 38 | AWSLambda awsLambdaClient = AWSLambdaClientBuilder.standard() 39 | .withClientConfiguration(clientConfiguration) 40 | .build(); 41 | 42 | final InvokeRequest request = new InvokeRequest(); 43 | return awsLambdaClient.invoke(request); 44 | } 45 | // {/fact} 46 | } 47 | -------------------------------------------------------------------------------- /src/java/detectors/aws_dynamodb_getitem_null_check/AwsDynamodbGetitemNullCheck.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.aws_dynamodb_getitem_null_check; 7 | 8 | import java.util.Map; 9 | import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; 10 | import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder; 11 | import com.amazonaws.services.dynamodbv2.model.AttributeValue; 12 | import com.amazonaws.services.dynamodbv2.model.GetItemRequest; 13 | import com.amazonaws.services.dynamodbv2.model.GetItemResult; 14 | import com.amazonaws.services.dynamodbv2.model.ResourceNotFoundException; 15 | import lombok.extern.slf4j.Slf4j; 16 | 17 | @Slf4j 18 | public class AwsDynamodbGetitemNullCheck { 19 | 20 | // {fact rule=aws-dynamodb-getitem-null-check@v1.0 defects=1} 21 | public void dynamoDBGetItemNoncompliant(Map key, String tableName) { 22 | AmazonDynamoDB dynamoDBClient = AmazonDynamoDBClientBuilder.standard().build(); 23 | GetItemRequest request = new GetItemRequest() 24 | .withTableName(tableName) 25 | .withKey(key); 26 | try { 27 | GetItemResult result = dynamoDBClient.getItem(request); 28 | // Noncompliant: result is not null-checked. 29 | System.out.println(result.getItem().get("key")); 30 | } catch (ResourceNotFoundException e) { 31 | log.error(e.getMessage()); 32 | } 33 | } 34 | // {/fact} 35 | 36 | // {fact rule=aws-dynamodb-getitem-null-check@v1.0 defects=0} 37 | public void dynamoDBGetItemCompliant(Map key, String tableName) { 38 | AmazonDynamoDB dynamoDBClient = AmazonDynamoDBClientBuilder.standard().build(); 39 | GetItemRequest request = new GetItemRequest() 40 | .withTableName(tableName) 41 | .withKey(key); 42 | try { 43 | GetItemResult result = dynamoDBClient.getItem(request); 44 | // Compliant: result is null-checked. 45 | if (result.getItem() != null) { 46 | System.out.println(result.getItem().get("key")); 47 | } 48 | } catch (ResourceNotFoundException e) { 49 | log.error(e.getMessage()); 50 | } 51 | } 52 | // {/fact} 53 | } 54 | -------------------------------------------------------------------------------- /src/java/detectors/aws_dynamodb_mapper_batch_output_ignored/AwsDynamodbMapperBatchOutputIgnoredCompliant.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.aws_dynamodb_mapper_batch_output_ignored; 7 | 8 | import com.amazonaws.regions.Regions; 9 | import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; 10 | import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder; 11 | import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; 12 | import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper.FailedBatch; 13 | import lombok.extern.slf4j.Slf4j; 14 | import org.springframework.stereotype.Repository; 15 | import stubs.DynamoBatchWriteOutputCompliant; 16 | import stubs.DynamoDBMapperCollection; 17 | import java.util.List; 18 | import java.util.stream.Collectors; 19 | 20 | // {fact rule=aws-dynamodb-mapper-batch-output-ignored@v1.0 defects=0} 21 | @Slf4j 22 | @Repository 23 | public class AwsDynamodbMapperBatchOutputIgnoredCompliant extends DynamoBatchWriteOutputCompliant { 24 | AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().withRegion(Regions.US_EAST_1).build(); 25 | DynamoDBMapper myDynamoDBMapper = new DynamoDBMapper(client); 26 | @Override 27 | public List mapperCompliant(DynamoDBMapperCollection batch) { 28 | // Compliant: has checks to handle errors returned by batch operation. 29 | List failures = myDynamoDBMapper.batchSave(batch); 30 | return failures.stream() 31 | .map(FailedBatch -> String.format("messageId:%s failedReason:%s", 32 | FailedBatch.getException(), 33 | FailedBatch.getUnprocessedItems())).collect(Collectors.toList()); 34 | } 35 | } 36 | // {/fact} 37 | -------------------------------------------------------------------------------- /src/java/detectors/aws_dynamodb_mapper_batch_output_ignored/AwsDynamodbMapperBatchOutputIgnoredNoncompliant.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.aws_dynamodb_mapper_batch_output_ignored; 7 | 8 | import com.amazonaws.regions.Regions; 9 | import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; 10 | import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder; 11 | import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; 12 | import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper.FailedBatch; 13 | import lombok.extern.slf4j.Slf4j; 14 | import org.springframework.stereotype.Repository; 15 | import stubs.DynamoBatchWriteOutputNoncompliant; 16 | import stubs.DynamoDBMapperCollection; 17 | import java.util.List; 18 | 19 | // {fact rule=aws-dynamodb-mapper-batch-output-ignored@v1.0 defects=1} 20 | @Slf4j 21 | @Repository 22 | public class AwsDynamodbMapperBatchOutputIgnoredNoncompliant extends DynamoBatchWriteOutputNoncompliant { 23 | //aws-dynamodb-mapper-batch-output-ignored@v1.0 24 | AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().withRegion(Regions.US_EAST_1).build(); 25 | DynamoDBMapper myDynamoDBMapper = new DynamoDBMapper(client); 26 | @Override 27 | public void mapperNoncompliant(DynamoDBMapperCollection batch) { 28 | // Noncompliant: does not have checks to handle errors returned by batch operation. 29 | List failures = myDynamoDBMapper.batchSave(batch); 30 | System.out.println("Completed Dynamo Batch Write Operation"); 31 | batch.clear(); 32 | } 33 | } 34 | // {/fact} 35 | -------------------------------------------------------------------------------- /src/java/detectors/aws_iam_error_prone_policy/AwsIamErrorPronePolicy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.aws_iam_error_prone_policy; 7 | 8 | import com.amazonaws.regions.Regions; 9 | import com.amazonaws.services.identitymanagement.AmazonIdentityManagement; 10 | import com.amazonaws.services.identitymanagement.AmazonIdentityManagementClientBuilder; 11 | import com.amazonaws.services.identitymanagement.model.CreateRoleRequest; 12 | import com.amazonaws.services.identitymanagement.model.GetRolePolicyRequest; 13 | import java.io.UnsupportedEncodingException; 14 | import java.net.URLDecoder; 15 | 16 | public class AwsIamErrorPronePolicy { 17 | // {fact rule=aws-iam-error-prone-policy@v1.0 defects=1} 18 | public void iamPolicyNoncompliant(final String roleName, String userArn) { 19 | final AmazonIdentityManagement iamClient = AmazonIdentityManagementClientBuilder.standard().withRegion(Regions.US_EAST_1).build(); 20 | String policyDocument = "{\n" + 21 | " \"Version\": \"2012-10-17\",\n" + 22 | " \"Statement\": [\n" + 23 | " {\n" + 24 | " \"Effect\": \"Allow\",\n" + 25 | " \"Principal\": {\n" + 26 | " \"AWS\": \"" + userArn + "\"\n" + 27 | " },\n" + 28 | " \"Action\": \"sts:AssumeRole\"\n" + 29 | " }\n" + 30 | " ]\n" + 31 | "}"; 32 | 33 | final CreateRoleRequest createRoleRequest = new CreateRoleRequest(); 34 | // Noncompliant: creates an IAM role/policy manually. 35 | createRoleRequest.withPath("path").withRoleName(roleName).withAssumeRolePolicyDocument(policyDocument); 36 | iamClient.createRole(createRoleRequest); 37 | } 38 | // {/fact} 39 | 40 | // {fact rule=aws-iam-error-prone-policy@v1.0 defects=0} 41 | public void iamPolicyCompliant(final String roleName) throws UnsupportedEncodingException { 42 | final AmazonIdentityManagement iamClient = AmazonIdentityManagementClientBuilder.standard().withRegion(Regions.US_EAST_1).build(); 43 | final String policyDocument = URLDecoder.decode(iamClient.getRolePolicy(new GetRolePolicyRequest()).getPolicyDocument(), "UTF-8"); 44 | final CreateRoleRequest createRoleRequest = new CreateRoleRequest() 45 | .withRoleName(roleName) 46 | .withAssumeRolePolicyDocument(policyDocument); 47 | // Compliant: creates an IAM role/policy automatically. 48 | final String policyArn = iamClient.createRole(createRoleRequest).getRole().getArn(); 49 | } 50 | // {/fact} 51 | } 52 | -------------------------------------------------------------------------------- /src/java/detectors/aws_inefficient_chain/AwsInefficientChain.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.aws_inefficient_chain; 7 | 8 | import com.amazonaws.regions.Regions; 9 | import com.amazonaws.services.s3.AmazonS3; 10 | import com.amazonaws.services.s3.AmazonS3ClientBuilder; 11 | import com.amazonaws.services.s3.model.S3Object; 12 | 13 | import java.io.IOException; 14 | 15 | public class AwsInefficientChain { 16 | // {fact rule=aws-inefficient-chain@v1.0 defects=1} 17 | private String inefficientApiCallsNoncompliant(final String bucketName, final String key) throws IOException { 18 | AmazonS3 s3Client = AmazonS3ClientBuilder.standard().withRegion(Regions.US_EAST_1).build(); 19 | // Noncompliant: uses inefficient chain of API calls over an efficient single API call. 20 | S3Object s3object = s3Client.getObject(bucketName, key); 21 | try { 22 | return s3object.getObjectMetadata().getVersionId(); 23 | } finally { 24 | s3object.close(); 25 | } 26 | 27 | } 28 | // {/fact} 29 | 30 | // {fact rule=aws-inefficient-chain@v1.0 defects=0} 31 | private String efficientApiCallsCompliant(final String bucketName, final String key) { 32 | AmazonS3 s3Client = AmazonS3ClientBuilder.standard().withRegion(Regions.US_EAST_1).build(); 33 | // Compliant: uses an efficient single API call over inefficient chain of API calls. 34 | return s3Client.getObjectMetadata(bucketName, key).getVersionId(); 35 | } 36 | // {/fact} 37 | } 38 | -------------------------------------------------------------------------------- /src/java/detectors/aws_kms_reencryption/AwsKmsReencryption.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.aws_kms_reencryption; 7 | 8 | import software.amazon.awssdk.core.SdkBytes; 9 | import software.amazon.awssdk.services.kms.KmsClient; 10 | import software.amazon.awssdk.services.kms.model.DecryptRequest; 11 | import software.amazon.awssdk.services.kms.model.EncryptRequest; 12 | import software.amazon.awssdk.services.kms.model.ReEncryptRequest; 13 | 14 | public class AwsKmsReencryption { 15 | // {fact rule=aws-kms-reencryption@v1.0 defects=1} 16 | public void withoutReEncryptNoncompliant(KmsClient client, SdkBytes encryptedContent) { 17 | 18 | DecryptRequest decryptRequest = DecryptRequest.builder() 19 | .ciphertextBlob(encryptedContent) 20 | .build(); 21 | SdkBytes plaintext = client.decrypt(decryptRequest).plaintext(); 22 | // Noncompliant: client-side decrypt immediately followed by encrypt. 23 | EncryptRequest encryptRequest = EncryptRequest.builder() 24 | .keyId("my-key-id") 25 | .plaintext(plaintext) 26 | .build(); 27 | client.encrypt(encryptRequest); 28 | } 29 | // {/fact} 30 | 31 | // {fact rule=aws-kms-reencryption@v1.0 defects=0} 32 | public void withReEncryptCompliant(KmsClient client, SdkBytes encryptedContent) { 33 | // Compliant: uses a ReEncryptRequest which runs server-side. 34 | ReEncryptRequest req = ReEncryptRequest.builder() 35 | .ciphertextBlob(encryptedContent) 36 | .destinationKeyId("my-key-id") 37 | .build(); 38 | client.reEncrypt(req).ciphertextBlob(); 39 | } 40 | // {/fact} 41 | } 42 | -------------------------------------------------------------------------------- /src/java/detectors/aws_parse_error_message/AwsParseErrorMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.aws_parse_error_message; 7 | 8 | import com.amazonaws.AmazonServiceException; 9 | import com.amazonaws.regions.Regions; 10 | import com.amazonaws.services.s3.AmazonS3; 11 | import com.amazonaws.services.s3.AmazonS3ClientBuilder; 12 | import lombok.extern.slf4j.Slf4j; 13 | 14 | @Slf4j 15 | public class AwsParseErrorMessage { 16 | // {fact rule=aws-parse-error-message@v1.0 defects=1} 17 | public void branchingNoncompliant() { 18 | AmazonS3 s3Client = AmazonS3ClientBuilder.standard().withRegion(Regions.US_EAST_1).build(); 19 | try { 20 | s3Client.doesObjectExist("bucketName", "key"); 21 | } catch (AmazonServiceException e) { 22 | // Noncompliant: checks the status message of the exception instead of the status code. 23 | if (e.getMessage().contains("bucketName")) { 24 | log.info("one thing"); 25 | } else { 26 | log.info("another thinking"); 27 | } 28 | } 29 | } 30 | // {/fact} 31 | 32 | // {fact rule=aws-parse-error-message@v1.0 defects=0} 33 | public void branchingCompliant() { 34 | AmazonS3 s3Client = AmazonS3ClientBuilder.standard().withRegion(Regions.US_EAST_1).build(); 35 | try { 36 | s3Client.doesObjectExist("bucketName", "key"); 37 | } catch (AmazonServiceException e) { 38 | // Compliant: checks the status code of the exception instead of the status message. 39 | if (e.getStatusCode() == 404){ 40 | log.info("The specified bucket does not exist."); 41 | } 42 | else { 43 | log.info("Caught error: " + e.getMessage()); 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/java/detectors/aws_region_enumeration/AwsRegionEnumeration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.aws_region_enumeration; 7 | 8 | import com.amazonaws.regions.Regions; 9 | import com.amazonaws.services.s3.AmazonS3; 10 | import com.amazonaws.services.s3.AmazonS3ClientBuilder; 11 | 12 | public class AwsRegionEnumeration { 13 | 14 | // {fact rule=aws-region-enumeration@v1.0 defects=1} 15 | public void createS3ClientNoncompliant() { 16 | // Noncompliant: a string is used to specify AWS region. 17 | AmazonS3 s3 = AmazonS3ClientBuilder.standard() 18 | .withRegion("us-west-2") 19 | .build(); 20 | } 21 | // {/fact} 22 | 23 | // {fact rule=aws-region-enumeration@v1.0 defects=0} 24 | public void createS3ClientCompliant() { 25 | // Compliant: Regions enum is used to specify AWS region. 26 | AmazonS3 s3 = AmazonS3ClientBuilder.standard() 27 | .withRegion(Regions.US_WEST_2) 28 | .build(); 29 | } 30 | // {/fact} 31 | } 32 | -------------------------------------------------------------------------------- /src/java/detectors/aws_service_client_initialization/AwsServiceClientInitializationCompliant.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.aws_service_client_initialization; 7 | 8 | import com.amazonaws.regions.Regions; 9 | import com.amazonaws.services.datapipeline.DataPipeline; 10 | import com.amazonaws.services.datapipeline.DataPipelineAsyncClientBuilder; 11 | import com.amazonaws.services.lambda.runtime.Context; 12 | import com.amazonaws.services.lambda.runtime.RequestHandler; 13 | 14 | // {fact rule=aws-service-client-initialization@v1.0 defects=0} 15 | public class AwsServiceClientInitializationCompliant implements RequestHandler { 16 | 17 | private DataPipeline dataPipeline; 18 | 19 | public void AwsServiceClientInitializationCompliant() { 20 | // Compliant: AWS region provider specified. 21 | dataPipeline = DataPipelineAsyncClientBuilder.standard().withRegion(Regions.US_WEST_2).build(); 22 | } 23 | 24 | @Override 25 | public Void handleRequest(String requestEvent, Context context) { 26 | // Handle the request here. 27 | return null; 28 | } 29 | } 30 | // {/fact} 31 | -------------------------------------------------------------------------------- /src/java/detectors/aws_service_client_initialization/AwsServiceClientInitializationNoncompliant.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.aws_service_client_initialization; 7 | 8 | import com.amazonaws.services.datapipeline.DataPipeline; 9 | import com.amazonaws.services.datapipeline.DataPipelineAsyncClientBuilder; 10 | import com.amazonaws.services.lambda.runtime.Context; 11 | import com.amazonaws.services.lambda.runtime.RequestHandler; 12 | 13 | // {fact rule=aws-service-client-initialization@v1.0 defects=1} 14 | public class AwsServiceClientInitializationNoncompliant implements RequestHandler { 15 | 16 | private DataPipeline dataPipeline; 17 | 18 | public void AwsServiceClientInitializationNoncompliant() { 19 | // Noncompliant: AWS region provider not specified. 20 | dataPipeline = DataPipelineAsyncClientBuilder.defaultClient(); 21 | } 22 | 23 | @Override 24 | public Void handleRequest(String requestEvent, Context context) { 25 | // Handle the request here. 26 | return null; 27 | } 28 | } 29 | // {/fact} 30 | -------------------------------------------------------------------------------- /src/java/detectors/batches_preferred_over_loops/BatchesPreferredOverLoops.java: -------------------------------------------------------------------------------- 1 | package detectors.batches_preferred_over_loops; 2 | 3 | import com.amazonaws.SdkClientException; 4 | import com.amazonaws.services.s3.AmazonS3; 5 | import com.amazonaws.services.s3.model.DeleteObjectRequest; 6 | import com.amazonaws.services.s3.model.DeleteObjectsRequest; 7 | import com.amazonaws.services.s3.model.DeleteObjectsResult; 8 | import lombok.extern.slf4j.Slf4j; 9 | import java.util.List; 10 | 11 | @Slf4j 12 | public class BatchesPreferredOverLoops { 13 | 14 | // {fact rule=batches-preferred-over-loops@v1.0 defects=1} 15 | public void deleteObjectsNoncompliant(AmazonS3 s3Client, List keys, 16 | String bucketName) throws SdkClientException { 17 | // Noncompliant: creates a separate request per item. 18 | for (final DeleteObjectsRequest.KeyVersion key : keys) { 19 | final DeleteObjectRequest deleteObjectRequest = new DeleteObjectRequest(bucketName, key.getKey()); 20 | s3Client.deleteObject(deleteObjectRequest); 21 | } 22 | } 23 | // {/fact} 24 | 25 | // {fact rule=batches-preferred-over-loops@v1.0 defects=0} 26 | public void deleteObjectsCompliant(AmazonS3 s3Client, List keys, 27 | String bucketName) throws SdkClientException { 28 | if(keys.size() <= 1000) { 29 | // Compliant: uses the batch operation instead of creating a separate request per item. 30 | final DeleteObjectsRequest deleteObjectRequest = new DeleteObjectsRequest(bucketName).withKeys(keys); 31 | DeleteObjectsResult deleteObjectsResult = s3Client.deleteObjects(deleteObjectRequest); 32 | final int numDeleted = deleteObjectsResult.getDeletedObjects().size(); 33 | log.info("Successfully deleted: " + numDeleted); 34 | } else { 35 | // To delete more than 1000 objects, deleteObjects needs to be called more than once. 36 | throw new IllegalArgumentException("Need multiple batch calls for >1000 objects."); 37 | } 38 | } 39 | // {/fact} 40 | } 41 | -------------------------------------------------------------------------------- /src/java/detectors/cipher_update_aad/CipherUpdateAAD.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.cipher_update_aad; 7 | 8 | import javax.crypto.SecretKey; 9 | import javax.crypto.spec.GCMParameterSpec; 10 | import javax.crypto.Cipher; 11 | import javax.crypto.spec.SecretKeySpec; 12 | import java.security.GeneralSecurityException; 13 | 14 | public class CipherUpdateAAD { 15 | 16 | // {fact rule=cipher-update-aad@v1.0 defects=1} 17 | public byte[] createCipherNoncompliant(byte[] key, int tagLength, byte[] ivSource, byte[] salt, byte[] data) 18 | throws GeneralSecurityException { 19 | 20 | SecretKey secretKeySpec = new SecretKeySpec(key, "AES"); 21 | GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(tagLength, ivSource); 22 | Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); 23 | // Noncompliant: Additional authenticated data (AAD) is not used. 24 | cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, gcmParameterSpec); 25 | return cipher.doFinal(data); 26 | } 27 | // {/fact} 28 | 29 | // {fact rule=cipher-update-aad@v1.0 defects=0} 30 | public byte[] createCipherCompliant(byte[] key, int tagLength, byte[] ivSource, byte[] salt, byte[] data) 31 | throws GeneralSecurityException { 32 | 33 | SecretKey secretKeySpec = new SecretKeySpec(key, "AES"); 34 | GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(tagLength, ivSource); 35 | Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); 36 | cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, gcmParameterSpec); 37 | // Compliant: Additional authenticated data (AAD) is used. 38 | cipher.updateAAD(salt); 39 | return cipher.doFinal(data); 40 | } 41 | // {/fact} 42 | } 43 | -------------------------------------------------------------------------------- /src/java/detectors/clear_text_credentials/ClearTextCredentials.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.clear_text_credentials; 7 | 8 | import lombok.extern.slf4j.Slf4j; 9 | import com.amazonaws.auth.AWSCredentials; 10 | import com.amazonaws.auth.DefaultAWSCredentialsProviderChain; 11 | 12 | @Slf4j 13 | public class ClearTextCredentials { 14 | 15 | // {fact rule=clear-text-credentials@v1.0 defects=1} 16 | public void logCredentialsNoncompliant() { 17 | String publicData = "some public data"; 18 | AWSCredentials credentials = new DefaultAWSCredentialsProviderChain().getCredentials(); 19 | // Noncompliant: secret access key is logged. 20 | log.error("somePublicData: " + publicData + " key: " + credentials.getAWSSecretKey()); 21 | } 22 | // {/fact} 23 | 24 | // {fact rule=clear-text-credentials@v1.0 defects=0} 25 | public void logCredentialsCompliant() { 26 | String publicData = "some public data"; 27 | AWSCredentials credentials = new DefaultAWSCredentialsProviderChain().getCredentials(); 28 | // Compliant: secret access key is not logged. 29 | log.error("somePublicData: " + publicData); 30 | } 31 | // {/fact} 32 | } 33 | -------------------------------------------------------------------------------- /src/java/detectors/client_constructor_deprecated_rule/ClientConstructorDeprecatedRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.client_constructor_deprecated_rule; 7 | 8 | import com.amazonaws.services.kinesis.AmazonKinesis; 9 | import com.amazonaws.services.kinesis.AmazonKinesisClient; 10 | import com.amazonaws.services.kinesis.AmazonKinesisClientBuilder; 11 | 12 | public class ClientConstructorDeprecatedRule { 13 | 14 | // {fact rule=client-constructor-deprecated-rule@v1.0 defects=1} 15 | public void createKinesisClientNoncompliant(){ 16 | // Noncompliant: deprecated client constructor used. 17 | AmazonKinesisClient producerKinesisClient = new AmazonKinesisClient(); 18 | } 19 | // {/fact} 20 | 21 | // {fact rule=client-constructor-deprecated-rule@v1.0 defects=0} 22 | public void createKinesisClientCompliant(String region) { 23 | // Compliant: client builder used. 24 | AmazonKinesis kinesis = AmazonKinesisClientBuilder.standard().withRegion(region).build(); 25 | } 26 | // {/fact} 27 | } 28 | -------------------------------------------------------------------------------- /src/java/detectors/code_clone/CodeCloneCompliant.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.code_clone; 7 | 8 | import lombok.extern.slf4j.Slf4j; 9 | import stubs.*; 10 | 11 | import java.nio.file.Path; 12 | import java.util.Map; 13 | 14 | @Slf4j 15 | public class CodeCloneCompliant { 16 | // {fact rule=code-clone@v1.0 defects=0} 17 | public ActivityJobItem getJobFromArnAndActivityType(String activityJobArn, ActivityType activityType){ 18 | ActivityJobItem activityJob = null; 19 | if (activityType == ActivityType.TRAINING) { 20 | activityJob = trainingJobDao.loadTrainingJob(activityJobArn); 21 | } else if (activityType == ActivityType.EVALUATION) { 22 | activityJob = evaluationJobDao.loadEvaluationJob(activityJobArn); 23 | } else if (activityType == ActivityType.FINETUNING) { 24 | activityJob = finetuningJobDao.loadFinetuningJob(activityJobArn); 25 | } 26 | return activityJob; 27 | } 28 | 29 | private boolean doesVideoStreamExistForJobCompliant(final String videoStreamArn, 30 | final String viewAngle, 31 | final String activityJobArn, 32 | final ActivityType activityType) throws Exception { 33 | try { 34 | ActivityJobItem activityJob = null; 35 | // Compliant: avoids using similar code fragments in the same file. 36 | activityJob = getJobFromArnAndActivityType(activityJobArn, activityType); 37 | if (activityJob == null) { 38 | throw new Exception("Unexpected workflow activity job."); 39 | } 40 | 41 | return containsVideoStreamWithGivenAngleAndArn(videoStreamArn, viewAngle, activityJob); 42 | } catch (Exception ex) { 43 | log.error("Unable to get video stream data from DynamoDB.", ex); 44 | throw ex; 45 | } 46 | } 47 | 48 | private void UpdateVideoInfoInDynamoDBCompliant(final Path videoFilePath, 49 | final String s3BucketName, 50 | final String activityJobArn, 51 | final ActivityType activityType) { 52 | String videoFileLocation = null; 53 | if ((videoFilePath != null) && (s3BucketName != null)) { 54 | String videoFileName = videoFilePath.toFile().getName(); 55 | videoFileLocation = "s3://" + s3BucketName + "/" + S3_OBJECT_KEY_PREFIX + videoFileName; 56 | } 57 | ActivityJobItem activityJob = null; 58 | // Compliant: avoids using similar code fragments in the same file. 59 | activityJob = getJobFromArnAndActivityType(activityJobArn, activityType); 60 | if (activityJob == null) { 61 | return; 62 | } 63 | 64 | updateActivityJobItem(activityJob, videoFileLocation, activityType); 65 | } 66 | // {/fact} 67 | 68 | String S3_OBJECT_KEY_PREFIX="Object_Key_Prefix"; 69 | 70 | private void updateActivityJobItem(ActivityJobItem activityJob, String videoFileLocation, ActivityType activityType) { 71 | } 72 | private boolean containsVideoStreamWithGivenAngleAndArn(final String videoStreamArn, 73 | final String viewAngle, 74 | final ActivityJobItem activityJob){ 75 | return true; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/java/detectors/code_clone/CodeCloneNoncompliant.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.code_clone; 7 | 8 | import lombok.extern.slf4j.Slf4j; 9 | import stubs.*; 10 | 11 | import java.nio.file.Path; 12 | import java.util.Map; 13 | 14 | @Slf4j 15 | public class CodeCloneNoncompliant { 16 | // {fact rule=code-clone@v1.0 defects=1} 17 | private boolean doesVideoStreamExistForJobNoncompliant(final String videoStreamArn, 18 | final String viewAngle, 19 | final String activityJobArn, 20 | final ActivityType activityType) throws Exception { 21 | try { 22 | ActivityJobItem activityJob = null; 23 | // Noncompliant: uses similar code fragments in the same file. 24 | if (activityType == ActivityType.TRAINING) { 25 | activityJob = trainingJobDao.loadTrainingJob(activityJobArn); 26 | } else if (activityType == ActivityType.EVALUATION) { 27 | activityJob = evaluationJobDao.loadEvaluationJob(activityJobArn); 28 | } else if (activityType == ActivityType.FINETUNING) { 29 | activityJob = finetuningJobDao.loadFinetuningJob(activityJobArn); 30 | } 31 | if (activityJob == null) { 32 | throw new Exception("Unexpected workflow activity job."); 33 | } 34 | 35 | return containsVideoStreamWithGivenAngleAndArn(videoStreamArn, viewAngle, activityJob); 36 | } catch (Exception ex) { 37 | log.error("Unable to get video stream data from DynamoDB.", ex); 38 | throw ex; 39 | } 40 | } 41 | 42 | private void updateVideoInfoInDynamoDBNoncompliant(final Path videoFilePath, 43 | final String s3BucketName, 44 | final String activityJobArn, 45 | final ActivityType activityType) { 46 | String videoFileLocation = null; 47 | if ((videoFilePath != null) && (s3BucketName != null)) { 48 | String videoFileName = videoFilePath.toFile().getName(); 49 | videoFileLocation = "s3://" + s3BucketName + "/" + S3_OBJECT_KEY_PREFIX + videoFileName; 50 | } 51 | ActivityJobItem activityJob = null; 52 | // Noncompliant: uses similar code fragments in the same file. 53 | if (activityType == ActivityType.TRAINING) { 54 | activityJob = trainingJobDao.loadTrainingJob(activityJobArn); 55 | } else if (activityType == ActivityType.EVALUATION) { 56 | activityJob = evaluationJobDao.loadEvaluationJob(activityJobArn); 57 | } else if (activityType == ActivityType.FINETUNING) { 58 | activityJob = finetuningJobDao.loadFinetuningJob(activityJobArn); 59 | } 60 | if (activityJob == null) { 61 | return; 62 | } 63 | 64 | updateActivityJobItem(activityJob, videoFileLocation, activityType); 65 | } 66 | // {/fact} 67 | 68 | String S3_OBJECT_KEY_PREFIX="Object_Key_Prefix"; 69 | private void updateActivityJobItem(ActivityJobItem activityJob, String videoFileLocation, ActivityType activityType) { 70 | } 71 | private boolean containsVideoStreamWithGivenAngleAndArn(final String videoStreamArn, 72 | final String viewAngle, 73 | final ActivityJobItem activityJob){ 74 | return true; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/java/detectors/code_injection/CodeInjection.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.code_injection; 7 | 8 | import javax.servlet.http.HttpServletRequest; 9 | import javax.script.ScriptException; 10 | import javax.script.ScriptEngineManager; 11 | import javax.script.ScriptEngine; 12 | 13 | public class CodeInjection { 14 | 15 | // {fact rule=code-injection@v1.0 defects=1} 16 | public void evaluateJavaScriptNoncompliant(HttpServletRequest request) throws ScriptException { 17 | final String parameter = request.getParameter("parameter"); 18 | ScriptEngineManager manager = new ScriptEngineManager(); 19 | ScriptEngine engine = manager.getEngineByName("JavaScript"); 20 | // Noncompliant: user-supplied parameter evaluated as a script. 21 | engine.eval(parameter); 22 | } 23 | // {/fact} 24 | 25 | // {fact rule=code-injection@v1.0 defects=0} 26 | public void evaluateJavaScriptCompliant(HttpServletRequest request) throws ScriptException { 27 | final String parameter = request.getParameter("parameter"); 28 | ScriptEngineManager manager = new ScriptEngineManager(); 29 | ScriptEngine engine = manager.getEngineByName("JavaScript"); 30 | // Compliant: user-supplied parameter must be in allow-list to be evaluated. 31 | if (!parameter.matches("[\\w]+")) { 32 | // String does not match allow-listed characters 33 | throw new IllegalArgumentException(); 34 | } 35 | engine.eval(parameter); 36 | } 37 | // {/fact} 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/java/detectors/concurrency_atomicity_violation/ConcurrencyAtomicityViolationCompliant.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.concurrency_atomicity_violation; 7 | 8 | import java.util.concurrent.ConcurrentHashMap; 9 | 10 | // {fact rule=concurrency-atomicity-violation@v1.0 defects=0} 11 | public class ConcurrencyAtomicityViolationCompliant { 12 | 13 | private ConcurrentHashMap concurrentMap = new ConcurrentHashMap(); 14 | 15 | public void getValue(String key) { 16 | // Compliant: the value is checked for null before being accessed. 17 | String value = concurrentMap.get(key); 18 | if (value != null) { 19 | System.out.println(value.length()); 20 | } 21 | } 22 | 23 | public void deleteValue(String key) { 24 | concurrentMap.remove(key); 25 | } 26 | } 27 | // {/fact} 28 | -------------------------------------------------------------------------------- /src/java/detectors/concurrency_atomicity_violation/ConcurrencyAtomicityViolationNoncompliant.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.concurrency_atomicity_violation; 7 | 8 | import java.util.concurrent.ConcurrentHashMap; 9 | 10 | // {fact rule=concurrency-atomicity-violation@v1.0 defects=1} 11 | public class ConcurrencyAtomicityViolationNoncompliant { 12 | 13 | private ConcurrentHashMap concurrentMap = new ConcurrentHashMap(); 14 | 15 | public void getValue(String key) { 16 | // Noncompliant: the key could be removed from the map between the first call and the second one. 17 | if (concurrentMap.containsKey(key)) { 18 | String value = concurrentMap.get(key); 19 | System.out.println(value.length()); 20 | } 21 | } 22 | 23 | public void deleteValue(String key) { 24 | concurrentMap.remove(key); 25 | } 26 | } 27 | // {/fact} 28 | -------------------------------------------------------------------------------- /src/java/detectors/concurrency_deadlock/ConcurrencyDeadlockCompliant.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.concurrency_deadlock; 7 | 8 | // {fact rule=concurrency-deadlock@v1.0 defects=0} 9 | public class ConcurrencyDeadlockCompliant { 10 | 11 | Object syncObject1 = new Object(); 12 | Object syncObject2 = new Object(); 13 | 14 | // Compliant: both methods request the two locks in the same order. 15 | 16 | public void compliantsync1() { 17 | synchronized (syncObject1) { 18 | synchronized (syncObject2) { 19 | System.out.println("Deadlock compliant example."); 20 | // Placeholder for code. 21 | } 22 | } 23 | } 24 | 25 | public void compliantsync2() { 26 | synchronized (syncObject1) { 27 | synchronized (syncObject2) { 28 | System.out.println("Deadlock compliant example."); 29 | // Placeholder for code. 30 | } 31 | } 32 | } 33 | } 34 | // {/fact} 35 | -------------------------------------------------------------------------------- /src/java/detectors/concurrency_deadlock/ConcurrencyDeadlockNoncompliant.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.concurrency_deadlock; 7 | 8 | // {fact rule=concurrency-deadlock@v1.0 defects=1} 9 | public class ConcurrencyDeadlockNoncompliant { 10 | 11 | Object syncObject1 = new Object(); 12 | Object syncObject2 = new Object(); 13 | 14 | // Noncompliant: both methods request the same two locks in the opposite order, which can cause deadlock. 15 | 16 | public void noncompliantsync1() { 17 | synchronized (syncObject1) { 18 | synchronized (syncObject2) { 19 | System.out.println("Deadlock noncompliant example."); 20 | // Placeholder for code. 21 | } 22 | } 23 | } 24 | 25 | public void noncompliantsync2() { 26 | synchronized (syncObject2) { 27 | synchronized (syncObject1) { 28 | System.out.println("Deadlock noncompliant example."); 29 | // Placeholder for code. 30 | } 31 | } 32 | } 33 | } 34 | // {/fact} 35 | -------------------------------------------------------------------------------- /src/java/detectors/concurrency_over_synchronization/ConcurrencyOverSynchronization.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.concurrency_over_synchronization; 7 | 8 | import java.util.concurrent.ConcurrentHashMap; 9 | 10 | public class ConcurrencyOverSynchronization { 11 | 12 | // {fact rule=concurrency-over-synchronization@v1.0 defects=1} 13 | public String putIfAbsentNoncompliant(ConcurrentHashMap concurrentMap, String key) { 14 | String sampleValue = "sampleString"; 15 | // Noncompliant: this is less efficient and more error-prone than using putIfAbsent. 16 | synchronized(this) { 17 | String value = concurrentMap.get(key); 18 | if (value == null) { 19 | concurrentMap.put(key, sampleValue); 20 | } 21 | return key; 22 | } 23 | } 24 | // {/fact} 25 | 26 | // {fact rule=concurrency-over-synchronization@v1.0 defects=0} 27 | public String putIfAbsentCompliant(ConcurrentHashMap concurrentMap, String key) { 28 | String sampleValue = "sampleString"; 29 | // Compliant: uses putIfAbsent instead of manual synchronization. 30 | concurrentMap.putIfAbsent(key, sampleValue); 31 | return key; 32 | } 33 | // {/fact} 34 | } 35 | -------------------------------------------------------------------------------- /src/java/detectors/cross_site_request_forgery/CrossSiteRequestForgery.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.cross_site_request_forgery; 7 | 8 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 9 | 10 | public class CrossSiteRequestForgery { 11 | 12 | // {fact rule=cross-site-request-forgery@v1.0 defects=1} 13 | public void configureCsrfNoncompliant(HttpSecurity security) throws Exception { 14 | // Noncompliant: disables CSRF protection. 15 | security.csrf().disable(); 16 | } 17 | // {/fact} 18 | 19 | // {fact rule=cross-site-request-forgery@v1.0 defects=0} 20 | public void configureCsrfCompliant(HttpSecurity security) throws Exception { 21 | // Compliant: enables CSRF protection. 22 | security.csrf(); 23 | } 24 | // {/fact} 25 | } 26 | -------------------------------------------------------------------------------- /src/java/detectors/cross_site_scripting/CrossSiteScripting.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.cross_site_scripting; 7 | 8 | import org.springframework.web.bind.annotation.RequestParam; 9 | import org.springframework.web.servlet.ModelAndView; 10 | 11 | public class CrossSiteScripting { 12 | 13 | // {fact rule=cross-site-scripting@v1.0 defects=1} 14 | public ModelAndView inputSanitizationNonCompliant(@RequestParam String favoriteColor) { 15 | ModelAndView modelAndView = new ModelAndView(); 16 | modelAndView.setViewName("jsp/example.jsp"); 17 | // Noncompliant: user-supplied parameter might contain malicious content. 18 | modelAndView.addObject("preferredColor", favoriteColor); 19 | return modelAndView; 20 | } 21 | // {/fact} 22 | 23 | // {fact rule=cross-site-scripting@v1.0 defects=0} 24 | public ModelAndView inputSanitizationCompliant(@RequestParam String favoriteColor) { 25 | ModelAndView modelAndView = new ModelAndView(); 26 | modelAndView.setViewName("jsp/example.jsp"); 27 | // Compliant: user-supplied parameter must be in allow-list. 28 | if (favoriteColor.matches("[a-z]+")) { 29 | modelAndView.addObject("preferredColor", favoriteColor); 30 | } else { 31 | throw new IllegalArgumentException("Invalid color!"); 32 | } 33 | return modelAndView; 34 | } 35 | // {/fact} 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/java/detectors/deprecated_method/DeprecatedMethod.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.deprecated_method; 7 | 8 | import org.springframework.security.crypto.codec.Base64; 9 | 10 | public class DeprecatedMethod { 11 | 12 | // {fact rule=deprecated-method@v1.0 defects=1} 13 | public String encodePasswordNoncompliant(String password) { 14 | // Noncompliant: uses deprecated Base64 class from Spring Framework. 15 | byte[] encodedId = Base64.encode(password.toLowerCase().getBytes()); 16 | return new String(encodedId); 17 | } 18 | // {/fact} 19 | 20 | // {fact rule=deprecated-method@v1.0 defects=0} 21 | public String encodePasswordCompliant(String password) { 22 | // Compliant: uses the standard Base64 class from the Java SDK.. 23 | byte[] encodedId = java.util.Base64.getEncoder().encode(password.toLowerCase().getBytes()); 24 | return new String(encodedId); 25 | } 26 | // {/fact} 27 | } 28 | -------------------------------------------------------------------------------- /src/java/detectors/dynamodb_transaction_library/DynamodbTransactionLibraryCompliant.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.dynamodb_transaction_library; 7 | 8 | import com.amazonaws.services.dynamodbv2.model.AttributeValue; 9 | import com.amazonaws.services.dynamodbv2.model.Put; 10 | import com.amazonaws.services.dynamodbv2.model.TransactWriteItem; 11 | import com.amazonaws.services.dynamodbv2.model.TransactWriteItemsRequest; 12 | import java.util.Collections; 13 | import java.util.Map; 14 | 15 | 16 | // {fact rule=dynamodb-transaction-library@v1.0 defects=0} 17 | public class DynamodbTransactionLibraryCompliant { 18 | public void DynamoDBTransactionLibraryCompliant(String name) throws InterruptedException { 19 | final Map item = createItem(); 20 | final Put put = new Put() 21 | .withTableName(name) 22 | .withItem(item); 23 | // Compliant: uses DynamoDB native transactional APIs over AWS Lab Transactions Library. 24 | final TransactWriteItem transactWriteItem = new TransactWriteItem().withPut(put); 25 | final TransactWriteItemsRequest request = new TransactWriteItemsRequest() 26 | .withTransactItems(transactWriteItem) 27 | .withReturnConsumedCapacity("TOTAL"); 28 | } 29 | 30 | private Map createItem() { 31 | Map item = Collections.emptyMap(); 32 | return item; 33 | } 34 | } 35 | // {/fact} 36 | -------------------------------------------------------------------------------- /src/java/detectors/dynamodb_transaction_library/DynamodbTransactionLibraryNoncompliant.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.dynamodb_transaction_library; 7 | 8 | // {fact rule=dynamodb-transaction-library@v1.0 defects=1} 9 | import com.amazonaws.services.dynamodbv2.transactions.TransactionManager; 10 | 11 | public class DynamodbTransactionLibraryNoncompliant { 12 | public void createTransactionNoncompliant() throws Exception { 13 | // Noncompliant: uses AWS Lab Transactions Library over DynamoDB native transactional APIs. 14 | TransactionManager.verifyOrCreateTransactionTable("client", "Transactions", 1, 1, null); 15 | } 16 | } 17 | // {/fact} 18 | -------------------------------------------------------------------------------- /src/java/detectors/file_syntax_error/FileSyntaxError.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.file_syntax_error; 7 | 8 | import com.amazonaws.services.s3.AmazonS3; 9 | import com.amazonaws.services.s3.model.S3Object; 10 | import java.io.IOException; 11 | import java.io.InputStream; 12 | import com.amazonaws.util.IOUtils; 13 | 14 | public class FileSyntaxError { 15 | 16 | // {fact rule=file-syntax-error@v1.0 defects=1} 17 | public void getObjectContentNoncompliant(AmazonS3 amazonS3Client, String bucketName, String key) throws IOException { 18 | final S3Object s3object = amazonS3Client.getObject(bucketName, key); 19 | // Noncompliant: the statement is incomplete and is missing ";" at the end. 20 | System.out.println(s3object.getObjectMetadata()) 21 | InputStream reportStream = s3object.getObjectContent(); 22 | IOUtils.toString(reportStream); 23 | } 24 | // {/fact} 25 | 26 | // {fact rule=file-syntax-error@v1.0 defects=0} 27 | public void getObjectContentCompliant(AmazonS3 amazonS3Client, String bucketName, String key) throws IOException { 28 | final S3Object s3object = amazonS3Client.getObject(bucketName, key); 29 | // Compliant: the statement is complete and ends with a ";". 30 | System.out.println(s3object.getObjectMetadata()); 31 | InputStream reportStream = s3object.getObjectContent(); 32 | IOUtils.toString(reportStream); 33 | } 34 | // {/fact} 35 | } 36 | -------------------------------------------------------------------------------- /src/java/detectors/finalize_on_super_class/FinalizeOnSuperClassCompliant.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.finalize_on_super_class; 7 | 8 | import java.io.BufferedReader; 9 | import java.io.IOException; 10 | 11 | // {fact rule=finalize-on-super-class@v1.0 defects=0} 12 | public class FinalizeOnSuperClassCompliant { 13 | protected abstract class FeedParser { 14 | @Override 15 | protected void finalize() throws IOException { 16 | System.out.println("finalize-class"); 17 | } 18 | } 19 | 20 | protected abstract class ETLFeedParserCompliant extends FeedParser { 21 | private BufferedReader feedReader; 22 | @Override 23 | // Compliant: calls super.finalize() explicitly. 24 | protected void finalize() throws IOException { 25 | try { 26 | feedReader.close(); 27 | } 28 | finally { 29 | super.finalize(); 30 | } 31 | } 32 | } 33 | } 34 | // {/fact} 35 | -------------------------------------------------------------------------------- /src/java/detectors/finalize_on_super_class/FinalizeOnSuperClassNoncompliant.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.finalize_on_super_class; 7 | 8 | import java.io.BufferedReader; 9 | import java.io.IOException; 10 | 11 | // {fact rule=finalize-on-super-class@v1.0 defects=1} 12 | public class FinalizeOnSuperClassNoncompliant { 13 | protected abstract class FeedParser { 14 | @Override 15 | protected abstract void finalize() throws IOException; 16 | } 17 | 18 | protected abstract class ETLFeedParser extends FeedParser { 19 | private BufferedReader feedReader; 20 | // Noncompliant: does not call super.finalize(). 21 | @Override 22 | protected void finalize() throws IOException { 23 | feedReader.close(); 24 | } 25 | } 26 | } 27 | // {/fact} 28 | -------------------------------------------------------------------------------- /src/java/detectors/hardcoded_credentials/HardcodedCredentials.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.hardcoded_credentials; 7 | 8 | import java.sql.Connection; 9 | import java.sql.DriverManager; 10 | 11 | public class HardcodedCredentials { 12 | 13 | // {fact rule=hardcoded-credentials@v1.0 defects=1} 14 | public void createSqlConnectionNoncompliant() throws Exception { 15 | // Noncompliant: password is hardcoded. 16 | final Connection connection = DriverManager.getConnection("some url", 17 | "username", "password"); 18 | connection.close(); 19 | } 20 | // {/fact} 21 | 22 | // {fact rule=hardcoded-credentials@v1.0 defects=0} 23 | public void createSqlConnectionCompliant() throws Exception { 24 | // Compliant: password is obtained from environment. 25 | final Connection connection = DriverManager.getConnection("some url", 26 | "user", System.getProperty("pwd")); 27 | connection.close(); 28 | } 29 | // {/fact} 30 | } 31 | -------------------------------------------------------------------------------- /src/java/detectors/http_response_splitting/HttpResponseSplitting.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.http_response_splitting; 7 | 8 | import io.netty.handler.codec.http.DefaultHttpHeaders; 9 | import javax.servlet.http.Cookie; 10 | import javax.servlet.http.HttpServletRequest; 11 | import javax.servlet.http.HttpServletResponse; 12 | 13 | public class HttpResponseSplitting { 14 | // {fact rule=http-response-splitting@v1.0 defects=1} 15 | public void headerSplittingProtectionDisabledNoncompliant() { 16 | // Noncompliant: false argument disables header validation. 17 | final DefaultHttpHeaders headers = new DefaultHttpHeaders(false); 18 | headers.clear(); 19 | } 20 | // {/fact} 21 | 22 | // {fact rule=http-response-splitting@v1.0 defects=1} 23 | public void addToCookieWithoutSanitizationNoncompliant(HttpServletRequest request, HttpServletResponse response) { 24 | final String name = request.getParameter("name"); 25 | // Noncompliant: parameter added to cookie might contain special chars. 26 | Cookie cookie = new Cookie("name", name); 27 | cookie.setSecure(true); 28 | response.addCookie(cookie); 29 | } 30 | // {/fact} 31 | 32 | // {fact rule=http-response-splitting@v1.0 defects=0} 33 | public void headerSplittingProtectionEnabledCompliant() { 34 | // Compliant: header validation is enabled by default. 35 | final DefaultHttpHeaders headers = new DefaultHttpHeaders(); 36 | headers.clear(); 37 | // Compliant: header validation is enabled explicitly. 38 | final DefaultHttpHeaders moreHeaders = new DefaultHttpHeaders(true); 39 | moreHeaders.clear(); 40 | } 41 | // {/fact} 42 | 43 | // {fact rule=http-response-splitting@v1.0 defects=0} 44 | public void addToCookieWithSanitizationCompliant(HttpServletRequest request, HttpServletResponse response) { 45 | // Compliant: parameter sanitized before adding to cookie. 46 | final String name = request.getParameter("name").replaceAll("[^a-zA-Z ]", ""); 47 | Cookie cookie = new Cookie("name", name); 48 | cookie.setSecure(true); 49 | response.addCookie(cookie); 50 | } 51 | // {/fact} 52 | } 53 | -------------------------------------------------------------------------------- /src/java/detectors/improper_locking/ImproperLockingCompliant.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.improper_locking; 7 | 8 | // {fact rule=improper-locking@v1.0 defects=0} 9 | public class ImproperLockingCompliant { 10 | 11 | Object main = new Object(); 12 | Object one = new Object(); 13 | Object two = new Object(); 14 | 15 | // Compliant: avoids deadlock by locking on the main. 16 | 17 | void firstMethod() { 18 | synchronized (main) { 19 | synchronized (one) { 20 | synchronized (two) { 21 | System.out.println("Task Complete!!!\n"); 22 | } 23 | } 24 | } 25 | } 26 | 27 | void secondMethod() { 28 | synchronized (main) { 29 | synchronized (two) { 30 | synchronized (one) { 31 | System.out.println("Task Complete!!!\n"); 32 | } 33 | } 34 | } 35 | } 36 | } 37 | // {/fact} 38 | -------------------------------------------------------------------------------- /src/java/detectors/improper_locking/ImproperLockingNoncompliant.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.improper_locking; 7 | 8 | // {fact rule=improper-locking@v1.0 defects=1} 9 | public class ImproperLockingNoncompliant { 10 | 11 | Object one = new Object(); 12 | Object two = new Object(); 13 | 14 | // Noncompliant: results in a classic deadlock by requesting two objects in the opposite order. 15 | 16 | // firstDeadlockMethod has one and is waiting on two. 17 | void firstDeadlockMethod() { 18 | synchronized(one) { 19 | synchronized(two) { 20 | System.out.println("Task Complete!!!\n"); 21 | } 22 | } 23 | } 24 | 25 | // secondDeadlockMethod has two and is waiting on one. 26 | void secondDeadlockMethod() { 27 | synchronized(two) { 28 | synchronized(one) { 29 | System.out.println("Task Complete!!!\n"); 30 | } 31 | } 32 | } 33 | } 34 | // {/fact} 35 | -------------------------------------------------------------------------------- /src/java/detectors/incorrect_authentication_exploitation/IncorrectAuthenticationExploitation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.incorrect_authentication_exploitation; 7 | 8 | import org.opensaml.xml.parse.BasicParserPool; 9 | 10 | public class IncorrectAuthenticationExploitation { 11 | // {fact rule=incorrect-authentication-exploitation@v1.0 defects=1} 12 | public void parserPoolNoncompliant(final BasicParserPool parser) { 13 | // Noncompliant: not ignoring comments creates a SAML authentication bypass vulnerability. 14 | parser.setIgnoreComments(false); 15 | } 16 | // {/fact} 17 | 18 | // {fact rule=incorrect-authentication-exploitation@v1.0 defects=0} 19 | public void parserPoolCompliant(final BasicParserPool parser) { 20 | // Compliant: ignoring comments prevents the SAML authentication bypass vulnerability. 21 | parser.setIgnoreComments(true); 22 | } 23 | // {/fact} 24 | } 25 | -------------------------------------------------------------------------------- /src/java/detectors/incorrect_null_check_before_setting/IncorrectNullCheckBeforeSetting.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.incorrect_null_check_before_setting; 7 | 8 | public class IncorrectNullCheckBeforeSetting { 9 | 10 | private String data1, data2; 11 | 12 | // {fact rule=incorrect-null-check-before-setting@v1.0 defects=1} 13 | public void nullCheckNoncompliant() { 14 | if (data1 != null) { 15 | // Noncompliant: overwriting immediately after a non-null check is likely to be a typo. 16 | data1 = data2; 17 | } 18 | } 19 | // {/fact} 20 | 21 | // {fact rule=incorrect-null-check-before-setting@v1.0 defects=0} 22 | public void nullCheckCompliant() { 23 | if (data1 == null) { 24 | // Compliant: overwriting after a null check is a common pattern. 25 | data1 = data2; 26 | } 27 | } 28 | // {/fact} 29 | } 30 | -------------------------------------------------------------------------------- /src/java/detectors/inefficient_apis/InefficientApis.java: -------------------------------------------------------------------------------- 1 | package rules.inefficient_apis; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import com.google.common.collect.Maps; 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | 10 | class InefficientApis extends Activity { 11 | 12 | // {fact rule=inefficient-apis@v1.0 defects=1} 13 | Map copyMapNonCompliant(Map parameterMap) { 14 | // Noncompliant: map will be rehashed after 75% of all keys have been added to the map. 15 | Map map = new HashMap(parameterMap.size()); 16 | for (Map.Entry entry : parameterMap.entrySet()) { 17 | map.put(entry.getKey(), entry.getValue()); 18 | } 19 | return map; 20 | } 21 | // {/fact} 22 | 23 | // {fact rule=inefficient-apis@v1.0 defects=0} 24 | Map copyMapCompliant(Map parameterMap) { 25 | // Compliant: map will not be rehashed because its expected size is provided. 26 | Map map = Maps.newHashMapWithExpectedSize(parameterMap.size()); 27 | for (Map.Entry entry : parameterMap.entrySet()) { 28 | map.put(entry.getKey(), entry.getValue()); 29 | } 30 | return map; 31 | } 32 | // {/fact} 33 | 34 | // {fact rule=inefficient-apis@v1.0 defects=1} 35 | public String getMessageNonCompliant(Bundle savedInstanceState) { 36 | Intent intent = getIntent(); 37 | // Noncompliant: using Serializable to pass data between different Android components. 38 | return (String) intent.getSerializableExtra("message"); 39 | } 40 | // {/fact} 41 | 42 | // {fact rule=inefficient-apis@v1.0 defects=0} 43 | public String getMessageCompliant(Bundle savedInstanceState) { 44 | Intent intent = getIntent(); 45 | // Compliant: using Parcelable to pass data between different Android components. 46 | return intent.getParcelableExtra("message"); 47 | } 48 | // {/fact} 49 | } 50 | -------------------------------------------------------------------------------- /src/java/detectors/infinite_loop/InfiniteLoop.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.infinite_loop; 7 | 8 | import stubs.ResultClass; 9 | import java.util.concurrent.TimeoutException; 10 | 11 | 12 | public class InfiniteLoop { 13 | 14 | // {fact rule=infinite-loop@v1.0 defects=1} 15 | public String loopControlNoncompliant() { 16 | ResultClass resultClass = new ResultClass(); 17 | // Noncompliant: does not have loop control flow to prevent an infinite loop. 18 | for ( ; ; ) { 19 | try { 20 | String result = resultClass.getResult(); 21 | return result; 22 | } catch (TimeoutException e) { 23 | resultClass.retry(); 24 | } 25 | } 26 | } 27 | // {/fact} 28 | 29 | // {fact rule=infinite-loop@v1.0 defects=0} 30 | public String loopControlCompliant() { 31 | ResultClass resultClass = new ResultClass(); 32 | // Compliant: has loop control flow to prevent an infinite loop. 33 | for (int i = 0; i < 10; ++i) { 34 | try { 35 | String result = resultClass.getResult(); 36 | return result; 37 | } catch (TimeoutException e) { 38 | resultClass.retry(); 39 | } 40 | } 41 | return null; 42 | } 43 | // {/fact} 44 | } 45 | -------------------------------------------------------------------------------- /src/java/detectors/insecure_connection/InsecureConnection.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.insecure_connection; 7 | 8 | import javax.net.ssl.HttpsURLConnection; 9 | import java.io.IOException; 10 | import java.net.HttpURLConnection; 11 | import java.net.URL; 12 | 13 | public class InsecureConnection { 14 | 15 | // {fact rule=insecure-connection@v1.0 defects=1} 16 | public void createConnectionNoncompliant() { 17 | try { 18 | URL url = new URL("http://www.example.com/"); 19 | // Noncompliant: creates an insecure http connection. 20 | HttpURLConnection httpUrlConnection = (HttpURLConnection) url.openConnection(); 21 | httpUrlConnection.setRequestMethod("GET"); 22 | httpUrlConnection.connect(); 23 | } catch (IOException e) { 24 | System.out.println(e); 25 | } 26 | } 27 | // {/fact} 28 | 29 | // {fact rule=insecure-connection@v1.0 defects=0} 30 | public void createConnectionCompliant() { 31 | try { 32 | // Compliant: creates a secure https connection. 33 | URL url = new URL("https://www.example.com/"); 34 | HttpsURLConnection httpsUrlConnection = (HttpsURLConnection) url.openConnection(); 35 | httpsUrlConnection.setRequestMethod("GET"); 36 | httpsUrlConnection.connect(); 37 | } catch (IOException e) { 38 | System.out.println(e); 39 | } 40 | } 41 | // {/fact} 42 | } 43 | -------------------------------------------------------------------------------- /src/java/detectors/insecure_cookie/InsecureCookie.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.insecure_cookie; 7 | 8 | import javax.servlet.http.Cookie; 9 | import javax.servlet.http.HttpServletResponse; 10 | 11 | public class InsecureCookie { 12 | // {fact rule=insecure-cookie@v1.0 defects=1} 13 | public static void cookieInsecureByDefaultNoncompliant(HttpServletResponse response) { 14 | Cookie cookie = new Cookie("name", "value"); 15 | // Noncompliant: by default, the Cookie is not secure and not httpOnly. 16 | response.addCookie(cookie); 17 | } 18 | // {/fact} 19 | 20 | // {fact rule=insecure-cookie@v1.0 defects=0} 21 | public static void cookieSecureCompliant(HttpServletResponse response) { 22 | Cookie cookie = new Cookie("name", "value"); 23 | // Compliant: the Cookie is secured. 24 | cookie.setSecure(true); 25 | cookie.setHttpOnly(true); 26 | response.addCookie(cookie); 27 | } 28 | // {/fact} 29 | } 30 | -------------------------------------------------------------------------------- /src/java/detectors/insecure_cors_policy/InsecureCorsPolicy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.insecure_cors_policy; 7 | 8 | import javax.servlet.http.HttpServletResponse; 9 | 10 | public class InsecureCorsPolicy { 11 | // {fact rule=insecure-cors-policy@v1.0 defects=1} 12 | public void allowOriginNoncompliant(HttpServletResponse response) { 13 | // Noncompliant: the Access-Control-Allow-Origin is set to allow any domain. 14 | response.setHeader("Access-Control-Allow-Origin", "*"); 15 | } 16 | // {/fact} 17 | 18 | // {fact rule=insecure-cors-policy@v1.0 defects=0} 19 | public void allowOriginCompliant(HttpServletResponse response) { 20 | // Compliant: the Access-Control-Allow-Origin is set to allow only a specific list of trusted domains. 21 | response.setHeader("Access-Control-Allow-Origin", "mytrustedsite.com"); 22 | } 23 | // {/fact} 24 | } 25 | -------------------------------------------------------------------------------- /src/java/detectors/insecure_cryptography/InsecureCryptography.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.insecure_cryptography; 7 | 8 | import java.security.KeyPairGenerator; 9 | import java.security.NoSuchAlgorithmException; 10 | 11 | public class InsecureCryptography { 12 | 13 | // {fact rule=insecure-cryptography@v1.0 defects=1} 14 | public void keyPairGeneratorNoncompliant() throws NoSuchAlgorithmException { 15 | KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); 16 | // Noncompliant: keysize too small for this algorithm. 17 | keyPairGenerator.initialize(128); 18 | keyPairGenerator.genKeyPair(); 19 | } 20 | // {/fact} 21 | 22 | // {fact rule=insecure-cryptography@v1.0 defects=0} 23 | public void keyPairGeneratorCompliant() throws NoSuchAlgorithmException { 24 | KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); 25 | // Compliant: keysize sufficient for this algorithm. 26 | keyPairGenerator.initialize(4096); 27 | keyPairGenerator.genKeyPair(); 28 | } 29 | // {/fact} 30 | } 31 | -------------------------------------------------------------------------------- /src/java/detectors/insecure_temporary_file/InsecureTemporaryFile.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.insecure_temporary_file; 7 | 8 | import java.io.File; 9 | import java.nio.file.Files; 10 | import java.nio.file.Path; 11 | import java.nio.file.Paths; 12 | 13 | public class InsecureTemporaryFile { 14 | // {fact rule=insecure-temporary-file@v1.0 defects=1} 15 | public void withDeleteNoncompliant() throws Exception { 16 | File tmp = File.createTempFile("myprefix", "mysuffix"); 17 | tmp.delete(); 18 | // Noncompliant: uses a temporary file path to create a temporary directory. 19 | tmp.mkdir(); 20 | } 21 | // {/fact} 22 | 23 | // {fact rule=insecure-temporary-file@v1.0 defects=0} 24 | public void usingCreateTempDirectoryCompliant() throws Exception { 25 | Path where = Paths.get("/tmp"); 26 | // Compliant: uses the correct mechanism to create a temporary directory. 27 | Path path = Files.createTempDirectory(where, "myprefix"); 28 | File tmpDir = path.toFile(); 29 | } 30 | // {/fact} 31 | } 32 | -------------------------------------------------------------------------------- /src/java/detectors/iterate_on_map_entries/IterateOnMapEntries.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.iterate_on_map_entries; 7 | 8 | import java.util.Map; 9 | 10 | 11 | public class IterateOnMapEntries { 12 | 13 | // {fact rule=iterate-on-map-entries@v1.0 defects=1} 14 | public void iterateOnKeySetUsingValuesNoncompliant(Map map) { 15 | // Noncompliant: iterate the set of keys and get the value of each key from the map. 16 | for (String name : map.keySet()) 17 | System.out.println("Value: " + map.get(name)); 18 | } 19 | // {/fact} 20 | 21 | // {fact rule=iterate-on-map-entries@v1.0 defects=0} 22 | public void iterateOnEntrySetCompliant(Map map) { 23 | // Compliant: iterate the set of map entries. 24 | for (Map.Entry entry : map.entrySet()) 25 | System.out.println("Key: " + entry.getKey() + 26 | ", Value: " + entry.getValue()); 27 | } 28 | // {/fact} 29 | } 30 | -------------------------------------------------------------------------------- /src/java/detectors/javax_persistence_id/JavaxPersistenceIdCompliant.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.javax_persistence_id; 7 | 8 | import lombok.AllArgsConstructor; 9 | import lombok.Builder; 10 | import lombok.Data; 11 | import lombok.NoArgsConstructor; 12 | import javax.persistence.Column; 13 | import javax.persistence.Entity; 14 | import javax.persistence.GeneratedValue; 15 | import javax.persistence.GenerationType; 16 | import javax.persistence.Id; 17 | import javax.persistence.Table; 18 | 19 | // {fact rule=javax-persistence-id@v1.0 defects=0} 20 | @Entity 21 | @Data 22 | @Builder 23 | @NoArgsConstructor 24 | @AllArgsConstructor 25 | @Table(name = "role_sla_type") 26 | public class JavaxPersistenceIdCompliant { 27 | 28 | // Compliant: does not attach an auto-incremented ID to 32-bit data. 29 | @GeneratedValue(strategy = GenerationType.IDENTITY) 30 | @Column(name = "role_sla_id", nullable = false) 31 | private Integer id; 32 | 33 | @Column(name = "type_id", nullable = false) 34 | private Integer typeId; 35 | 36 | @Id 37 | @Column(name = "type", nullable = false, length = 255) 38 | private String type; 39 | } 40 | // {/fact} 41 | -------------------------------------------------------------------------------- /src/java/detectors/javax_persistence_id/JavaxPersistenceIdNoncompliant.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.javax_persistence_id; 7 | 8 | import lombok.AllArgsConstructor; 9 | import lombok.Builder; 10 | import lombok.Data; 11 | import lombok.NoArgsConstructor; 12 | import javax.persistence.Column; 13 | import javax.persistence.Entity; 14 | import javax.persistence.GeneratedValue; 15 | import javax.persistence.GenerationType; 16 | import javax.persistence.Id; 17 | 18 | // {fact rule=javax-persistence-id@v1.0 defects=1} 19 | @Entity 20 | @Data 21 | @Builder 22 | @NoArgsConstructor 23 | @AllArgsConstructor 24 | public class JavaxPersistenceIdNoncompliant { 25 | 26 | // Noncompliant: attaches an auto-incremented ID to 32-bit data 27 | @Id 28 | @GeneratedValue(strategy = GenerationType.IDENTITY) 29 | @Column(name = "role_sla_id", nullable = false) 30 | private Integer id; 31 | 32 | @Column(name = "type_id", nullable = false) 33 | private Integer typeId; 34 | 35 | @Column(name = "type", nullable = false, length = 255) 36 | private String type; 37 | } 38 | // {/fact} 39 | -------------------------------------------------------------------------------- /src/java/detectors/json_parser_length/JsonParserLength.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.json_parser_length; 7 | 8 | import hivemall.utils.io.FastByteArrayInputStream; 9 | import org.apache.hadoop.io.Text; 10 | import com.fasterxml.jackson.core.JsonFactory; 11 | import java.io.IOException; 12 | 13 | public class JsonParserLength { 14 | 15 | // {fact rule=json-parser-length@v1.0 defects=1} 16 | public void createJsonParserNoncompliant(Text text) throws IOException { 17 | // Noncompliant: length of input byte array not specified. 18 | new JsonFactory().createJsonParser(new FastByteArrayInputStream(text.getBytes())); 19 | } 20 | // {/fact} 21 | 22 | // {fact rule=json-parser-length@v1.0 defects=0} 23 | public void createJsonParserCompliant(Text text) throws IOException { 24 | // Compliant: length of input byte array specified. 25 | new JsonFactory().createJsonParser(new FastByteArrayInputStream(text.getBytes(), text.getLength())); 26 | } 27 | // {/fact} 28 | } 29 | -------------------------------------------------------------------------------- /src/java/detectors/kcl_with_call_process_records/KclWithCallProcessRecords.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.kcl_with_call_process_records; 7 | 8 | import com.amazonaws.auth.AWSCredentialsProvider; 9 | import com.amazonaws.services.kinesis.clientlibrary.lib.worker.InitialPositionInStream; 10 | import com.amazonaws.services.kinesis.clientlibrary.lib.worker.KinesisClientLibConfiguration; 11 | 12 | public class KclWithCallProcessRecords { 13 | 14 | // {fact rule=kcl-with-call-process-records@v1.0 defects=1} 15 | public KinesisClientLibConfiguration configureKCLNoncompliant() { 16 | // Noncompliant: doesn't set withCallProcessRecordsEvenForEmptyRecordList to true during Kinesis Client Library (KCL) initialization. 17 | KinesisClientLibConfiguration kclConfig = new KinesisClientLibConfiguration(applicationName, 18 | streamARN, ddbStreamCredentials, workerID) 19 | .withMaxRecords(maxRecords) 20 | .withIdleTimeBetweenReadsInMillis(idleTimeBetweenReadsInMillis) 21 | .withFailoverTimeMillis(leaseFailOverTimeInMillis) 22 | .withInitialPositionInStream(InitialPositionInStream.TRIM_HORIZON); 23 | return kclConfig; 24 | } 25 | // {/fact} 26 | 27 | // {fact rule=kcl-with-call-process-records@v1.0 defects=0} 28 | public KinesisClientLibConfiguration configureKCLCompliant() { 29 | // Compliant: sets withCallProcessRecordsEvenForEmptyRecordList to true during Kinesis Client Library (KCL) initialization. 30 | KinesisClientLibConfiguration kclConfig = new KinesisClientLibConfiguration(applicationName, 31 | streamARN, ddbStreamCredentials, workerID) 32 | .withMaxRecords(maxRecords) 33 | .withCallProcessRecordsEvenForEmptyRecordList(true) 34 | .withIdleTimeBetweenReadsInMillis(idleTimeBetweenReadsInMillis) 35 | .withFailoverTimeMillis(leaseFailOverTimeInMillis) 36 | .withInitialPositionInStream(InitialPositionInStream.TRIM_HORIZON); 37 | return kclConfig; 38 | } 39 | // {/fact} 40 | 41 | private String applicationName; 42 | private String streamARN; 43 | private AWSCredentialsProvider ddbStreamCredentials; 44 | private String workerID; 45 | private int maxRecords; 46 | private long idleTimeBetweenReadsInMillis; 47 | private long leaseFailOverTimeInMillis; 48 | } 49 | -------------------------------------------------------------------------------- /src/java/detectors/lambda_client_reuse/LambdaClientReuseCompliant.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.lambda_client_reuse; 7 | 8 | import com.amazonaws.services.lambda.runtime.Context; 9 | import com.amazonaws.services.lambda.runtime.RequestHandler; 10 | import com.amazonaws.services.s3.AmazonS3; 11 | import com.amazonaws.services.s3.AmazonS3ClientBuilder; 12 | import com.amazonaws.services.s3.AmazonS3URI; 13 | import com.amazonaws.regions.Regions; 14 | 15 | // {fact rule=lambda-client-reuse@v1.0 defects=0} 16 | public class LambdaClientReuseCompliant implements RequestHandler { 17 | 18 | private AmazonS3 s3Client; 19 | 20 | public LambdaClientReuseCompliant() { 21 | // Compliant: creates the client only once. 22 | this.s3Client = AmazonS3ClientBuilder.standard() 23 | .withRegion(Regions.US_EAST_1).build(); 24 | } 25 | 26 | public Void handleRequest(String requestEvent, Context context) { 27 | System.err.println("Nothing to see here"); 28 | createBucketCompliant(); 29 | insertObjectCompliant("storeOject"); 30 | return null; 31 | } 32 | 33 | private void createBucketCompliant() { 34 | // Compliant: uses the cached client. 35 | s3Client.createBucket("storeObject"); 36 | } 37 | 38 | private void insertObjectCompliant(String s3Folder) { 39 | AmazonS3URI amazonS3URI = new AmazonS3URI(s3Folder); 40 | // Compliant: uses the cached client. 41 | s3Client.putObject(amazonS3URI.getBucket(), amazonS3URI.getKey(), "hello"); 42 | } 43 | } 44 | // {/fact} 45 | -------------------------------------------------------------------------------- /src/java/detectors/lambda_client_reuse/LambdaClientReuseNoncompliant.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.lambda_client_reuse; 7 | 8 | import com.amazonaws.regions.Regions; 9 | import com.amazonaws.services.lambda.runtime.Context; 10 | import com.amazonaws.services.lambda.runtime.RequestHandler; 11 | import com.amazonaws.services.s3.AmazonS3; 12 | import com.amazonaws.services.s3.AmazonS3ClientBuilder; 13 | 14 | // {fact rule=lambda-client-reuse@v1.0 defects=1} 15 | public class LambdaClientReuseNoncompliant implements RequestHandler { 16 | 17 | private AmazonS3 s3Client; 18 | 19 | 20 | public Void handleRequest(String requestEvent, Context context) { 21 | System.err.println("Nothing to see here"); 22 | createBucketNoncompliant(); 23 | return null; 24 | } 25 | 26 | private void createBucketNoncompliant() { 27 | s3Client.createBucket("bucketName"); 28 | // Noncompliant: recreates AWS clients in each lambda invocation. 29 | this.s3Client = AmazonS3ClientBuilder.standard() 30 | .withRegion(Regions.US_EAST_1).build(); 31 | } 32 | } 33 | // {/fact} 34 | -------------------------------------------------------------------------------- /src/java/detectors/lambda_override_reserved/LambdaOverrideReservedCompliant.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.lambda_override_reserved; 7 | 8 | import com.amazonaws.services.lambda.runtime.Context; 9 | import com.amazonaws.services.lambda.runtime.RequestHandler; 10 | import java.util.Map; 11 | 12 | // {fact rule=lambda-override-reserved@v1.0 defects=0} 13 | public class LambdaOverrideReservedCompliant implements RequestHandler { 14 | public Void handleRequest(String requestEvent, Context context) { 15 | final Map environment = new ProcessBuilder().environment(); 16 | // Compliant: does not override any reserved environment variable names in a Lambda function. 17 | environment.put("LANG", "en_US.UTF-8"); 18 | return null; 19 | } 20 | } 21 | // {/fact} 22 | -------------------------------------------------------------------------------- /src/java/detectors/lambda_override_reserved/LambdaOverrideReservedNoncompliant.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.lambda_override_reserved; 7 | 8 | import com.amazonaws.services.lambda.runtime.Context; 9 | import com.amazonaws.services.lambda.runtime.RequestHandler; 10 | import java.util.Map; 11 | 12 | // {fact rule=lambda-override-reserved@v1.0 defects=1} 13 | public class LambdaOverrideReservedNoncompliant implements RequestHandler { 14 | public Void handleRequest(String requestEvent, Context context) { 15 | final Map environment = new ProcessBuilder().environment(); 16 | // Noncompliant: overrides reserved environment variable names in a Lambda function. 17 | environment.put("AWS_REGION", "us-west-2"); 18 | return null; 19 | } 20 | } 21 | // {/fact} 22 | -------------------------------------------------------------------------------- /src/java/detectors/ldap_authentication/LdapAuthentication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.ldap_authentication; 7 | 8 | import javax.naming.Context; 9 | import javax.naming.NamingException; 10 | import javax.naming.directory.DirContext; 11 | import javax.naming.directory.InitialDirContext; 12 | import java.util.Hashtable; 13 | 14 | public class LdapAuthentication { 15 | 16 | // {fact rule=ldap-authentication@v1.0 defects=1} 17 | public void createDirContextNoncompliant(String password) throws NamingException { 18 | Hashtable environment = new Hashtable<>(); 19 | environment.put(Context.INITIAL_CONTEXT_FACTORY, "ldap context factory"); 20 | environment.put(Context.PROVIDER_URL, "context provider url"); 21 | // Noncompliant: authentication disabled. 22 | environment.put(Context.SECURITY_AUTHENTICATION, "none"); 23 | DirContext dirContext = new InitialDirContext(environment); 24 | } 25 | // {/fact} 26 | 27 | // {fact rule=ldap-authentication@v1.0 defects=0} 28 | public void createDirContextCompliant(String password) throws NamingException { 29 | Hashtable environment = new Hashtable<>(); 30 | environment.put(Context.INITIAL_CONTEXT_FACTORY, "ldap context factory"); 31 | environment.put(Context.PROVIDER_URL, "context provider url"); 32 | // Compliant: simple security authentication used. 33 | environment.put(Context.SECURITY_AUTHENTICATION, "simple"); 34 | environment.put(Context.SECURITY_PRINCIPAL, "a=something, b=something, c=something else"); 35 | environment.put(Context.SECURITY_CREDENTIALS, password); 36 | DirContext dirContext = new InitialDirContext(environment); 37 | } 38 | // {/fact} 39 | } 40 | -------------------------------------------------------------------------------- /src/java/detectors/ldap_injection/LdapInjection.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.ldap_injection; 7 | 8 | import javax.naming.NamingException; 9 | import javax.naming.directory.InitialDirContext; 10 | import javax.naming.directory.DirContext; 11 | import javax.naming.directory.SearchControls; 12 | import javax.naming.directory.SearchResult; 13 | import javax.servlet.http.HttpServletRequest; 14 | import javax.naming.NamingEnumeration; 15 | 16 | public class LdapInjection { 17 | 18 | // {fact rule=ldap-injection@v1.0 defects=1} 19 | public void ldapSearchNoncompliant(HttpServletRequest request) { 20 | try { 21 | DirContext directoryContext = new InitialDirContext(); 22 | SearchControls controls = new SearchControls(); 23 | final String filter = request.getParameter("filter"); 24 | Object[] args = new Object[]{"Some object"}; 25 | String base = "some base"; 26 | // Noncompliant: unsanitized user-supplied filter is used. 27 | NamingEnumeration results = 28 | directoryContext.search(base, filter, args, controls); 29 | System.out.println(results); 30 | } catch (NamingException e) { 31 | System.out.println(e); 32 | } 33 | } 34 | // {/fact} 35 | 36 | // {fact rule=ldap-injection@v1.0 defects=0} 37 | public void ldapSearchCompliant(HttpServletRequest request) { 38 | try { 39 | DirContext directoryContext = new InitialDirContext(); 40 | SearchControls controls = new SearchControls(); 41 | final String filter = request.getParameter("filter"); 42 | // Compliant: user-supplied filter is checked for allowed characters to prevent ldap injection. 43 | if (!filter.matches("[a-z]+")) { 44 | throw new IllegalArgumentException(); 45 | } 46 | Object[] args = new Object[]{"Some object"}; 47 | String base = "some base"; 48 | NamingEnumeration results = 49 | directoryContext.search(base, filter, args, controls); 50 | System.out.println(results); 51 | } catch (NamingException e) { 52 | System.out.println(e); 53 | } 54 | } 55 | // {/fact} 56 | } 57 | -------------------------------------------------------------------------------- /src/java/detectors/log_injection/LogInjection.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.log_injection; 7 | 8 | import javax.servlet.http.HttpServletRequest; 9 | import lombok.extern.slf4j.Slf4j; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.servlet.ModelAndView; 12 | 13 | @Slf4j 14 | public class LogInjection { 15 | 16 | // {fact rule=log-injection@v1.0 defects=1} 17 | @RequestMapping("/example.htm") 18 | public ModelAndView loggingNonCompliant(HttpServletRequest request) { 19 | ModelAndView result = new ModelAndView("success"); 20 | String userId = request.getParameter("userId"); 21 | result.addObject("userId", userId); 22 | // More logic here to populate the result. 23 | // Noncompliant: unsanitized input is logged. 24 | log.info("Successfully processed request for user ID: {}.", userId); 25 | return result; 26 | } 27 | // {/fact} 28 | 29 | // {fact rule=log-injection@v1.0 defects=0} 30 | @RequestMapping("/example.htm") 31 | public ModelAndView loggingCompliant(HttpServletRequest request) { 32 | ModelAndView result = new ModelAndView("success"); 33 | String userId = request.getParameter("userId"); 34 | String sanitizedUserId = sanitize(userId); 35 | result.addObject("userId", sanitizedUserId); 36 | // More logic here to populate the result. 37 | // Compliant: input is sanitized before logging. 38 | log.info("Successfully processed request for user ID: {}.", sanitizedUserId); 39 | return result; 40 | } 41 | 42 | private static String sanitize(String userId) { 43 | // Remove all chars except digits. 44 | return userId.replaceAll("\\D", ""); 45 | } 46 | // {/fact} 47 | } 48 | -------------------------------------------------------------------------------- /src/java/detectors/loose_file_permissions/LooseFilePermissions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.loose_file_permissions; 7 | 8 | import java.nio.file.Files; 9 | import java.nio.file.Path; 10 | import java.nio.file.attribute.PosixFilePermission; 11 | import java.nio.file.attribute.PosixFilePermissions; 12 | import java.util.Set; 13 | 14 | public class LooseFilePermissions { 15 | // {fact rule=loose-file-permissions@v1.0 defects=1} 16 | public void grantOthersPermissionsNoncompliant(final Path p) throws Exception { 17 | Set permissions = PosixFilePermissions.fromString("------rwx"); 18 | // Noncompliant: Granting other permissions. 19 | Files.setPosixFilePermissions(p, permissions); 20 | } 21 | // {/fact} 22 | 23 | // {fact rule=loose-file-permissions@v1.0 defects=0} 24 | public void grantGroupPermissionsCompliant(final Path p) throws Exception { 25 | Set permissions = PosixFilePermissions.fromString("---rwx---"); 26 | // Compliant: Granting group permissions. 27 | Files.setPosixFilePermissions(p, permissions); 28 | } 29 | // {/fact} 30 | } 31 | -------------------------------------------------------------------------------- /src/java/detectors/mandatory_methods/MandatoryMethods.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.mandatory_methods; 7 | import com.amazonaws.services.simplesystemsmanagement.model.PutParameterRequest; 8 | 9 | public class MandatoryMethods { 10 | // {fact rule=mandatory-methods@v1.0 defects=1} 11 | public void checkParameterDescriptionAllCallNoncompliant() { 12 | // Noncompliant: does not call mandatory methods on the object after its creation. 13 | PutParameterRequest putParameterRequest = new PutParameterRequest(); 14 | putParameterRequest.setName("parameterName"); 15 | } 16 | // {/fact} 17 | 18 | // {fact rule=mandatory-methods@v1.0 defects=0} 19 | public void checkParameterDescriptionAllCallCompliant() { 20 | // Compliant: calls the mandatory methods on the objects after its creation. 21 | PutParameterRequest putParameterRequest = new PutParameterRequest(); 22 | putParameterRequest.setDescription("Description"); 23 | putParameterRequest.setName("parameterName"); 24 | } 25 | // {/fact} 26 | } 27 | -------------------------------------------------------------------------------- /src/java/detectors/missing_check_on_android_startactivity/MissingCheckOnAndroidStartActivity.java: -------------------------------------------------------------------------------- 1 | package rules.missing_check_on_android_startactivity; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | 6 | class MissingCheckOnAndroidStartActivity { 7 | 8 | // {fact rule=missing-check-on-android-startactivity@v1.0 defects=1} 9 | public void startActivityNonCompliant(Context context, Intent shareIntent) { 10 | // Noncompliant: there might be no application on the device to receive the implicit intent. 11 | context.startActivity(shareIntent); 12 | } 13 | // {/fact} 14 | 15 | // {fact rule=missing-check-on-android-startactivity@v1.0 defects=0} 16 | public boolean startActivityCompliant(Context context, Intent shareIntent) { 17 | if (shareIntent.resolveActivity(context.getPackageManager()) != null) { 18 | // Compliant: called only if there is an application on the device to receive the implicit intent. 19 | context.startActivity(shareIntent); 20 | return true; 21 | } 22 | return false; 23 | } 24 | // {/fact} 25 | } 26 | -------------------------------------------------------------------------------- /src/java/detectors/missing_check_on_createnewfile/MissingCheckOnCreateNewFile.java: -------------------------------------------------------------------------------- 1 | package rules.missing_check_on_createnewfile; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.util.Optional; 6 | import lombok.extern.log4j.Log4j; 7 | 8 | @Log4j 9 | class MissingCheckOnCreateNewFile { 10 | 11 | // {fact rule=missing-check-on-createnewfile@v1.0 defects=1} 12 | public File createFileNonCompliant(File outputFolder, final String fileName) throws IOException { 13 | File file = new File(outputFolder, fileName); 14 | // Noncompliant: does not check if createNewFile succeeded or failed. 15 | file.createNewFile(); 16 | return file; 17 | } 18 | // {/fact} 19 | 20 | // {fact rule=missing-check-on-createnewfile@v1.0 defects=0} 21 | public Optional createFileCompliant(File outputFolder, final String fileName) throws IOException { 22 | File file = new File(outputFolder, fileName); 23 | // Compliant: handles the case when createNewFile fails. 24 | if (!file.createNewFile()) { 25 | log.debug("File already exists, using existing file " + file.getAbsolutePath() + "."); 26 | return Optional.empty(); 27 | } 28 | return Optional.of(file); 29 | } 30 | // {/fact} 31 | } 32 | -------------------------------------------------------------------------------- /src/java/detectors/missing_check_on_method_output/MissingCheckOnMethodOutput.java: -------------------------------------------------------------------------------- 1 | package rules.missing_check_on_method_output; 2 | 3 | import java.io.File; 4 | import java.io.FileOutputStream; 5 | import java.io.IOException; 6 | import lombok.extern.log4j.Log4j; 7 | 8 | @Log4j 9 | class MissingCheckOnMethodOutput { 10 | 11 | // {fact rule=missing-check-on-method-output@v1.0 defects=1} 12 | private void writeMessageNonCompliant(String dirName, String fileName, String message) { 13 | try { 14 | File dir = new File(dirName); 15 | if (!dir.exists()) { 16 | // Noncompliant: code does not handle the case when mkdirs fails. 17 | dir.mkdirs(); 18 | } 19 | try (FileOutputStream fos = new FileOutputStream(new File(dir, fileName))) { 20 | fos.write(message.getBytes()); 21 | } 22 | } catch (IOException e) { 23 | e.printStackTrace(); 24 | } 25 | } 26 | // {/fact} 27 | 28 | // {fact rule=missing-check-on-method-output@v1.0 defects=0} 29 | private void writeMessageCompliant(String dirName, String fileName, String message) { 30 | try { 31 | File dir = new File(dirName); 32 | boolean ok = true; 33 | if (!dir.exists()) { 34 | // Compliant: code handles the case when mkdirs fails. 35 | ok = dir.mkdirs(); 36 | } 37 | if (ok) { 38 | try (FileOutputStream fos = new FileOutputStream(new File(dir, fileName))) { 39 | fos.write(message.getBytes()); 40 | } 41 | } else { 42 | log.warn("output directory not created"); 43 | } 44 | } catch (IOException e) { 45 | e.printStackTrace(); 46 | } 47 | } 48 | // {/fact} 49 | } 50 | -------------------------------------------------------------------------------- /src/java/detectors/missing_file_deletion_result_check/MissingFileDeletionResultCheck.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.missing_file_deletion_result_check; 7 | 8 | import java.io.File; 9 | import lombok.extern.slf4j.Slf4j; 10 | 11 | @Slf4j 12 | public class MissingFileDeletionResultCheck { 13 | 14 | // {fact rule=missing-file-deletion-result-check@v1.0 defects=1} 15 | public void fileDeletionNoncompliant(File file) { 16 | if (file.exists()) { 17 | log.info("Deleting file: " + file.getName()); 18 | // Noncompliant: result of file deletion not checked. 19 | file.delete(); 20 | } 21 | } 22 | // {/fact} 23 | 24 | // {fact rule=missing-file-deletion-result-check@v1.0 defects=0} 25 | public void fileDeletionCompliant(File file) { 26 | if (file.exists()) { 27 | log.info("Deleting file: " + file.getName()); 28 | // Compliant: result of file deletion is checked. 29 | if (!file.delete()) { 30 | throw new RuntimeException("Failed to delete the file!"); 31 | } 32 | } 33 | } 34 | // {/fact} 35 | } 36 | -------------------------------------------------------------------------------- /src/java/detectors/missing_getcause_on_invocationtargetexception/MissingGetCauseOnInvocationTargetException.java: -------------------------------------------------------------------------------- 1 | package rules.missing_getcause_on_invocationtargetexception; 2 | 3 | import java.lang.reflect.InvocationTargetException; 4 | import java.lang.reflect.Method; 5 | 6 | class MissingGetCauseOnInvocationTargetException { 7 | 8 | // {fact rule=missing-getcause-on-invocationtargetexception@v1.0 defects=1} 9 | public Object invokeMethodNonCompliant(Method method, Object[] args) throws Throwable { 10 | // Noncompliant: InvocationTargetException is not caught. 11 | return method.invoke(args); 12 | } 13 | // {/fact} 14 | 15 | // {fact rule=missing-getcause-on-invocationtargetexception@v1.0 defects=0} 16 | public Object invokeMethodCompliant(Object proxy, Method method, Object[] args) throws Throwable { 17 | try { 18 | // Compliant: InvocationTargetException is caught and e.getCause() is propagated further. 19 | Object returnValue = method.invoke(args); 20 | return returnValue; 21 | } catch (InvocationTargetException e) { 22 | throw e.getTargetException(); 23 | } 24 | } 25 | // {/fact} 26 | } 27 | -------------------------------------------------------------------------------- /src/java/detectors/missing_position_check_before_substring/MissingPositionCheckBeforeSubstring.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.missing_position_check_before_substring; 7 | 8 | public class MissingPositionCheckBeforeSubstring { 9 | 10 | // {fact rule=missing-position-check-before-substring@v1.0 defects=1} 11 | public void checkSubStringNoncompliant(String sampleString) { 12 | final String sampleSubstring = "sample"; 13 | final int index = sampleString.lastIndexOf(sampleSubstring); 14 | // Noncompliant: it is not checked if substring is part of the string. 15 | final String subString = sampleString.substring(0, index); 16 | } 17 | // {/fact} 18 | 19 | // {fact rule=missing-position-check-before-substring@v1.0 defects=0} 20 | public void checkSubStringCompliant(String sampleString) { 21 | final String sampleSubstring = "sample"; 22 | final int index = sampleString.lastIndexOf(sampleSubstring); 23 | // Compliant: checked if substring is part of the string. 24 | final String subString = index > 0 ? sampleString.substring(0, index) : sampleString; 25 | } 26 | // {/fact} 27 | } 28 | -------------------------------------------------------------------------------- /src/java/detectors/missing_specifically_thrown_exception_handling/MissingSpecificallyThrownExceptionHandling.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.missing_specifically_thrown_exception_handling; 7 | 8 | import lombok.extern.slf4j.Slf4j; 9 | 10 | @Slf4j 11 | public class MissingSpecificallyThrownExceptionHandling { 12 | 13 | // {fact rule=missing-specifically-thrown-exception-handling@v1.0 defects=1} 14 | public void exceptionHandlingNoncompliant() { 15 | // Noncompliant: catch block handles generic Exception, but not SomeException. 16 | try { 17 | doSomething(); 18 | throw new SomeException(); 19 | } catch (IndexOutOfBoundsException e) { 20 | log.error(e.getMessage()); 21 | } catch (Exception e) { 22 | log.error(e.getMessage()); 23 | } 24 | } 25 | // {/fact} 26 | 27 | // {fact rule=missing-specifically-thrown-exception-handling@v1.0 defects=0} 28 | public void exceptionHandlingCompliant() { 29 | // Compliant: catch block handles SomeException. 30 | try { 31 | doSomething(); 32 | throw new SomeException(); 33 | } catch (IndexOutOfBoundsException e) { 34 | log.error(e.getMessage()); 35 | } catch (SomeException e) { 36 | log.error(e.getMessage()); 37 | } catch (Exception e) { 38 | log.error(e.getMessage()); 39 | 40 | } 41 | } 42 | // {/fact} 43 | 44 | private void doSomething() { 45 | // Placeholder for code. 46 | } 47 | 48 | public class SomeException extends Exception { 49 | // Placeholder for SomeException definition. 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/java/detectors/missing_timeout_check_on_awaittermination/MissingTimeoutCheckOnAwaitTermination.java: -------------------------------------------------------------------------------- 1 | package rules.missing_timeout_check_on_awaittermination; 2 | 3 | import java.util.concurrent.ExecutorService; 4 | import java.util.concurrent.TimeUnit; 5 | import lombok.extern.log4j.Log4j; 6 | 7 | @Log4j 8 | class MissingTimeoutCheckOnAwaitTermination { 9 | 10 | // {fact rule=missing-timeout-check-on-awaittermination@v1.0 defects=1} 11 | public void shutdownNonCompliant(ExecutorService executor) { 12 | executor.shutdown(); 13 | try { 14 | // Noncompliant: awaitTermination might silently time out before all threads finish their execution. 15 | executor.awaitTermination(10, TimeUnit.SECONDS); 16 | } catch (InterruptedException e) { 17 | log.warn("Failed to wait for all tasks to finish", e); 18 | } 19 | } 20 | // {/fact} 21 | 22 | // {fact rule=missing-timeout-check-on-awaittermination@v1.0 defects=0} 23 | public void shutdownCompliant(ExecutorService executor) { 24 | executor.shutdown(); 25 | try { 26 | // Compliant: code handles the case when awaitTermination times out. 27 | if (!executor.awaitTermination(10, TimeUnit.SECONDS)) { 28 | log.warn("Failed to terminate executor"); 29 | } 30 | } catch (InterruptedException e) { 31 | log.warn("Failed to wait for all tasks to finish", e); 32 | } 33 | } 34 | // {/fact} 35 | } 36 | -------------------------------------------------------------------------------- /src/java/detectors/missing_timeout_check_on_latch_await/MissingTimeoutCheckOnLatchAwait.java: -------------------------------------------------------------------------------- 1 | package rules.missing_timeout_check_on_latch_await; 2 | 3 | import java.util.concurrent.CountDownLatch; 4 | import java.util.concurrent.ExecutionException; 5 | import java.util.concurrent.TimeUnit; 6 | import java.util.concurrent.TimeoutException; 7 | 8 | class MissingTimeoutCheckOnLatchAwait { 9 | 10 | private volatile Object result = null; 11 | private CountDownLatch completionLatch = new CountDownLatch(1); 12 | 13 | // {fact rule=missing-timeout-check-on-latch-await@v1.0 defects=1} 14 | public Object getResultNonCompliant(long timeout, TimeUnit unit) 15 | throws InterruptedException, ExecutionException, TimeoutException { 16 | 17 | // Noncompliant: code does not check if await timed out or the latch counted down to zero. 18 | completionLatch.await(timeout, unit); 19 | return result; 20 | } 21 | // {/fact} 22 | 23 | // {fact rule=missing-timeout-check-on-latch-await@v1.0 defects=0} 24 | public Object getResultCompliant(long timeout, TimeUnit unit) 25 | throws InterruptedException, ExecutionException, TimeoutException { 26 | 27 | // Compliant: code handles the case when await times out. 28 | if (!completionLatch.await(timeout, unit)) { 29 | throw new TimeoutException(); 30 | } 31 | return result; 32 | } 33 | // {/fact} 34 | } 35 | -------------------------------------------------------------------------------- /src/java/detectors/mutually_exclusive_calls_found/MutuallyExclusiveCallsFound.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.mutually_exclusive_calls_found; 7 | 8 | import com.amazonaws.regions.Regions; 9 | import com.amazonaws.services.ec2.AmazonEC2; 10 | import com.amazonaws.services.ec2.AmazonEC2ClientBuilder; 11 | import com.amazonaws.services.ec2.model.*; 12 | 13 | public class MutuallyExclusiveCallsFound { 14 | 15 | // {fact rule=mutually-exclusive-calls-found@v1.0 defects=1} 16 | public void ec2RunInstancesNoncompliant(String templateName, String templateID, String zone) { 17 | AmazonEC2 ec2Client = AmazonEC2ClientBuilder.standard().withRegion(Regions.US_WEST_2).build(); 18 | // Noncompliant: uses mutually exclusive withLaunchTemplateId and withLaunchTemplateName together. 19 | RunInstancesResult runInstancesResult = ec2Client.runInstances( 20 | new RunInstancesRequest() 21 | .withPlacement(new Placement().withAvailabilityZone(zone)) 22 | .withInstanceType(InstanceType.T2Micro) 23 | .withInstanceInitiatedShutdownBehavior("terminate") 24 | .withMinCount(1) 25 | .withMaxCount(2) 26 | .withLaunchTemplate( 27 | new LaunchTemplateSpecification() 28 | .withLaunchTemplateName(templateName) 29 | .withLaunchTemplateId(templateID) 30 | ) 31 | ); 32 | } 33 | // {/fact} 34 | 35 | // {fact rule=mutually-exclusive-calls-found@v1.0 defects=0} 36 | public void ec2RunInstancesCompliant(String templateName, String templateID, String zone) { 37 | AmazonEC2 ec2Client = AmazonEC2ClientBuilder.standard().withRegion(Regions.US_WEST_2).build(); 38 | // Compliant: uses only withLaunchTemplateId. 39 | RunInstancesResult runInstancesResult = ec2Client.runInstances( 40 | new RunInstancesRequest() 41 | .withPlacement(new Placement().withAvailabilityZone(zone)) 42 | .withInstanceType(InstanceType.T2Micro) 43 | .withInstanceInitiatedShutdownBehavior("terminate") 44 | .withMinCount(1) 45 | .withMaxCount(2) 46 | .withLaunchTemplate( 47 | new LaunchTemplateSpecification() 48 | .withLaunchTemplateId(templateID) 49 | ) 50 | ); 51 | } 52 | // {/fact} 53 | } 54 | -------------------------------------------------------------------------------- /src/java/detectors/not_recommended_apis/NotRecommendedApis.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.not_recommended_apis; 7 | 8 | import com.amazonaws.regions.Regions; 9 | import com.amazonaws.services.s3.AmazonS3; 10 | import com.amazonaws.services.s3.AmazonS3ClientBuilder; 11 | import com.amazonaws.services.s3.model.InitiateMultipartUploadRequest; 12 | import com.amazonaws.services.s3.model.PutObjectRequest; 13 | import com.amazonaws.services.s3.transfer.TransferManager; 14 | import com.amazonaws.services.s3.transfer.TransferManagerBuilder; 15 | import com.amazonaws.services.s3.transfer.Upload; 16 | 17 | public class NotRecommendedApis { 18 | // {fact rule=not-recommended-apis@v1.0 defects=1} 19 | public void s3MultiPartUploadNoncompliant() { 20 | AmazonS3 s3Client = AmazonS3ClientBuilder.standard() 21 | .withRegion(Regions.US_EAST_1) 22 | .build(); 23 | // Noncompliant: uses an API that we don't recommend, and a better alternative exists. 24 | s3Client.initiateMultipartUpload(new InitiateMultipartUploadRequest(bucketName,key)); 25 | } 26 | // {/fact} 27 | 28 | // {fact rule=not-recommended-apis@v1.0 defects=0} 29 | public void shutdownTransferManagerCompliant(final PutObjectRequest putRequest) { 30 | TransferManager transferManager = null; 31 | try { 32 | transferManager = TransferManagerBuilder.defaultTransferManager(); 33 | final Upload upload = transferManager.upload(putRequest); 34 | upload.waitForCompletion(); 35 | } catch (InterruptedException e) { 36 | Thread.currentThread().interrupt(); 37 | } finally { 38 | // Compliant: uses recommended APIs from TransferManager. 39 | transferManager.shutdownNow(); 40 | } 41 | } 42 | // {/fact} 43 | 44 | String bucketName = null; 45 | String key= null; 46 | } 47 | -------------------------------------------------------------------------------- /src/java/detectors/null_check_cache_response_metadata/NullCheckCacheResponseMetadata.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.null_check_cache_response_metadata; 7 | 8 | import com.amazonaws.services.s3.AmazonS3; 9 | import com.amazonaws.services.s3.S3ResponseMetadata; 10 | import com.amazonaws.AmazonWebServiceRequest; 11 | import lombok.extern.slf4j.Slf4j; 12 | 13 | @Slf4j 14 | public class NullCheckCacheResponseMetadata { 15 | 16 | // {fact rule=null-check-cache-response-metadata@v1.0 defects=1} 17 | public void getCachedResponseMetadataNoncompliant(AmazonWebServiceRequest request, AmazonS3 amazonS3Client) { 18 | S3ResponseMetadata responseMetadata = amazonS3Client.getCachedResponseMetadata(request); 19 | // Noncompliant: uses the result of getCachedResponseMetadata without null-checking it. 20 | log.info("Request ID: " + responseMetadata.getRequestId()); 21 | } 22 | // {/fact} 23 | 24 | // {fact rule=null-check-cache-response-metadata@v1.0 defects=0} 25 | public void getCachedResponseMetadataCompliant(AmazonWebServiceRequest request, AmazonS3 amazonS3Client) { 26 | S3ResponseMetadata responseMetadata = amazonS3Client.getCachedResponseMetadata(request); 27 | // Compliant: ensures that the result of getCachedResponseMetadata is not null before using it. 28 | if (responseMetadata != null) { 29 | log.info("Request ID: " + responseMetadata.getRequestId()); 30 | } else { 31 | log.info("Could not obtain cached metadata."); 32 | } 33 | } 34 | // {/fact} 35 | } 36 | -------------------------------------------------------------------------------- /src/java/detectors/null_pointer_dereference/NullPointerDereference.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.null_pointer_dereference; 7 | 8 | import javax.annotation.Nullable; 9 | 10 | public class NullPointerDereference { 11 | // {fact rule=null-pointer-dereference@v1.0 defects=1} 12 | private Double nullCheckPointerNoncompliant(@Nullable Double digit) { 13 | // Noncompliant: avoids null checks before dereferencing the pointer. 14 | return digit + 1.0; 15 | } 16 | // {/fact} 17 | 18 | // {fact rule=null-pointer-dereference@v1.0 defects=0} 19 | private Double nullCheckPointerCompliant(@Nullable Double digit) { 20 | // Compliant: has null checks before derefencing the pointer. 21 | if (digit != null) { 22 | return digit + 1.0; 23 | } 24 | return 1.0; 25 | } 26 | // {/fact} 27 | } 28 | -------------------------------------------------------------------------------- /src/java/detectors/object_presence/ObjectPresence.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.object_presence; 7 | 8 | import com.amazonaws.services.s3.AmazonS3; 9 | 10 | public class ObjectPresence { 11 | 12 | // {fact rule=object-presence@v1.0 defects=1} 13 | public boolean checkS3ObjectNoncompliant(AmazonS3 s3Client, String bucketName, String key) { 14 | // Noncompliant: implements an object existence check from scratch instead of using doesObjectExist. 15 | try { 16 | s3Client.getObjectMetadata(bucketName, key); 17 | return true; 18 | } catch (Exception e) { 19 | return false; 20 | } 21 | } 22 | // {/fact} 23 | 24 | // {fact rule=object-presence@v1.0 defects=0} 25 | public boolean checkS3ObjectCompliant(AmazonS3 s3Client, String bucketName, String key) { 26 | // Compliant: uses doesObjectExist instead of implementing it from scratch. 27 | try { 28 | return s3Client.doesObjectExist(bucketName, key); 29 | } catch (Exception e) { 30 | return false; 31 | } 32 | } 33 | // {/fact} 34 | } 35 | -------------------------------------------------------------------------------- /src/java/detectors/old_android_features/OldAndroidFeatures.java: -------------------------------------------------------------------------------- 1 | package rules.old_android_features; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.TextView; 9 | 10 | import stubs.ViewHolder; 11 | 12 | class OldAndroidFeatures extends Activity { 13 | 14 | int layoutResourceId = 0; 15 | 16 | // {fact rule=old-android-features@v1.0 defects=1} 17 | public ViewHolder onCreateViewHolderNonCompliant(ViewGroup parent, int viewType) { 18 | // Noncompliant: layout is created programmatically in code, without using the LayoutInflater. 19 | return new ViewHolder(new TextView(parent.getContext())); 20 | } 21 | // {/fact} 22 | 23 | // {fact rule=old-android-features@v1.0 defects=0} 24 | public ViewHolder onCreateViewHolderCompliant(ViewGroup parent, int viewType) { 25 | final Context context = parent.getContext(); 26 | // Compliant: LayoutInflater is used to inflate views. 27 | LayoutInflater inflater = LayoutInflater.from(context); 28 | View itemView = inflater.inflate(layoutResourceId, parent, false); 29 | return new ViewHolder(itemView); 30 | } 31 | // {/fact} 32 | } 33 | -------------------------------------------------------------------------------- /src/java/detectors/os_command_injection/OsCommandInjection.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.os_command_injection; 7 | 8 | import javax.servlet.http.HttpServletRequest; 9 | import java.io.IOException; 10 | 11 | public class OsCommandInjection { 12 | 13 | // {fact rule=os-command-injection@v1.0 defects=1} 14 | public void createProcessNoncompliant(HttpServletRequest request) { 15 | String favoriteColor = request.getParameter("favoriteColor"); 16 | // Noncompliant: user-supplied parameter is passed to an OS command and could be malicious. 17 | ProcessBuilder pb = new ProcessBuilder("/usr/local/bin/program", "--color", favoriteColor); 18 | try { 19 | pb.start(); 20 | } catch (IOException e) { 21 | System.out.println(e); 22 | } 23 | } 24 | // {/fact} 25 | 26 | // {fact rule=os-command-injection@v1.0 defects=0} 27 | public void createProcessCompliant(HttpServletRequest request) { 28 | String favoriteColor = request.getParameter("favoriteColor"); 29 | // Compliant: user-supplied parameter is sanitized before passing it to an OS command. 30 | if (!favoriteColor.matches("[a-z]+")) { 31 | throw new IllegalArgumentException(); 32 | } 33 | ProcessBuilder pb = new ProcessBuilder("/usr/local/bin/program", "--color", favoriteColor); 34 | try { 35 | pb.start(); 36 | } catch (IOException e) { 37 | System.out.println(e); 38 | } 39 | } 40 | // {/fact} 41 | } 42 | -------------------------------------------------------------------------------- /src/java/detectors/out_of_sync_input_and_output/OutOfSyncInputAndOutput.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.out_of_sync_input_and_output; 7 | 8 | import lombok.extern.slf4j.Slf4j; 9 | 10 | @Slf4j 11 | public abstract class OutOfSyncInputAndOutput { 12 | // {fact rule=out-of-sync-input-and-output@v1.0 defects=1} 13 | void outOfSyncNoncompliant(String deploymentId) { 14 | String deploymentItem = null; 15 | try { 16 | // Noncompliant: the output value would not be updated if the producing method 17 | // throws an exception, resulting the input and output values becoming out of sync. 18 | deploymentItem = loadDeployment(deploymentId); 19 | } catch (final Exception e) { 20 | log.warn("Exception: ", e); 21 | } 22 | doSomething(deploymentId, deploymentItem); 23 | } 24 | // {/fact} 25 | 26 | // {fact rule=out-of-sync-input-and-output@v1.0 defects=0} 27 | void outOfSyncCompliant(String deploymentId) { 28 | String deploymentItem = null; 29 | try { 30 | deploymentItem = loadDeployment(deploymentId); 31 | } catch (final Exception e) { 32 | log.warn("Exception: ", e); 33 | deploymentId=null; 34 | } 35 | // Compliant: the input value is reset, resulting the input and output values to stay in sync. 36 | doSomething(deploymentId, deploymentItem); 37 | } 38 | // {/fact} 39 | 40 | abstract String loadDeployment(String deploymentId); 41 | 42 | abstract void doSomething(String a, String b); 43 | } 44 | -------------------------------------------------------------------------------- /src/java/detectors/output_ignored_on_movetofirst_operation/OutputIgnoredOnMoveToFirstOperation.java: -------------------------------------------------------------------------------- 1 | package rules.output_ignored_on_movetofirst_operation; 2 | 3 | import android.content.Context; 4 | import android.database.Cursor; 5 | import android.net.Uri; 6 | 7 | class OutputIgnoredOnMoveToFirstOperation { 8 | 9 | // {fact rule=output-ignored-on-movetofirst-operation@v1.0 defects=1} 10 | public static String getDataFromURINonCompliant(Context context, Uri uri) { 11 | String[] columns = { "name", "address" }; 12 | try (Cursor cursor = context.getContentResolver().query(uri, columns, null, null, null)) { 13 | // Noncompliant: code does not check if the cursor is empty. 14 | cursor.moveToFirst(); 15 | return cursor.getString(0); 16 | } 17 | } 18 | // {/fact} 19 | 20 | // {fact rule=output-ignored-on-movetofirst-operation@v1.0 defects=0} 21 | public static String getDataFromURICompliant(Context context, Uri uri) { 22 | String[] columns = { "name", "address" }; 23 | try (Cursor cursor = context.getContentResolver().query(uri, columns, null, null, null)) { 24 | // Compliant: code handles the case when the cursor is empty. 25 | if (!cursor.moveToFirst()) { 26 | return null; 27 | } 28 | return cursor.getString(0); 29 | } 30 | } 31 | // {/fact} 32 | } 33 | -------------------------------------------------------------------------------- /src/java/detectors/partial_encryption/PartialEncryption.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.partial_encryption; 7 | 8 | import com.amazonaws.services.s3.AmazonS3; 9 | import com.amazonaws.services.s3.model.PutObjectRequest; 10 | import com.amazonaws.services.s3.model.SSEAwsKeyManagementParams; 11 | import java.io.File; 12 | 13 | public class PartialEncryption { 14 | 15 | // {fact rule=partial-encryption@v1.0 defects=1} 16 | public void s3PutObjectNoncompliant(AmazonS3 s3Client, String bucketName, String partFileKey, String kmsKeyId, 17 | File partFile, String bucketOwner) { 18 | PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, partFileKey, partFile).withExpectedBucketOwner(bucketOwner); 19 | // Noncompliant: encryption is not performed in all paths. 20 | if (kmsKeyId != null) { 21 | putObjectRequest.setSSEAwsKeyManagementParams(new SSEAwsKeyManagementParams(kmsKeyId)); 22 | } 23 | s3Client.putObject(putObjectRequest); 24 | } 25 | // {/fact} 26 | 27 | // {fact rule=partial-encryption@v1.0 defects=0} 28 | public void s3PutObjectCompliant(AmazonS3 s3Client, String bucketName, String partFileKey, String kmsKeyId, 29 | File partFile, String bucketOwner) { 30 | PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, partFileKey, partFile).withExpectedBucketOwner(bucketOwner); 31 | // Compliant: encryption is performed in all paths. 32 | if (kmsKeyId != null) { 33 | putObjectRequest.setSSEAwsKeyManagementParams(new SSEAwsKeyManagementParams(kmsKeyId)); 34 | } 35 | else { 36 | putObjectRequest.setSSEAwsKeyManagementParams(new SSEAwsKeyManagementParams()); 37 | } 38 | s3Client.putObject(putObjectRequest); 39 | } 40 | // {/fact} 41 | } 42 | -------------------------------------------------------------------------------- /src/java/detectors/path_traversal/PathTraversal.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.path_traversal; 7 | 8 | import javax.servlet.http.HttpServletRequest; 9 | import javax.servlet.http.HttpServletResponse; 10 | import java.io.File; 11 | 12 | public class PathTraversal { 13 | 14 | // {fact rule=path-traversal@v1.0 defects=1} 15 | public void createFileNoncompliant(HttpServletRequest request, HttpServletResponse response) { 16 | String basePath = "/var/data/images/"; 17 | String desiredCategory = request.getParameter("category"); 18 | // Noncompliant: user-supplied relative path is not sanitized and could contain malicious characters. 19 | File fileTarget = new File(basePath + desiredCategory); 20 | } 21 | // {/fact} 22 | 23 | // {fact rule=path-traversal@v1.0 defects=0} 24 | public void createFileCompliant(HttpServletRequest request) { 25 | String basePath = "/var/data/images/"; 26 | String desiredCategory = request.getParameter("category"); 27 | // Compliant: user-supplied relative path is sanitized before use. 28 | if (desiredCategory.matches("[a-z]+")) { 29 | File fileTarget = new File(basePath + desiredCategory); 30 | } else { 31 | throw new IllegalArgumentException("Invalid category name"); 32 | } 33 | } 34 | // {/fact} 35 | } 36 | -------------------------------------------------------------------------------- /src/java/detectors/reassign_synchronized_object/ReassignSynchronizedObject.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.reassign_synchronized_object; 7 | 8 | public class ReassignSynchronizedObject { 9 | Object mutex, mutex_one; 10 | // {fact rule=reassign-synchronized-object@v1.0 defects=1} 11 | private void assignSynchronizedObjectNoncompliant() { 12 | // Noncompliant: synchronized objects re-assigned in the same synchronized block. 13 | synchronized (mutex) { 14 | mutex = new Object(); 15 | doSomething(mutex); 16 | } 17 | } 18 | // {/fact} 19 | 20 | // {fact rule=reassign-synchronized-object@v1.0 defects=0} 21 | private void assignSynchronizingObjectCompliant() { 22 | // Compliant: avoids re-assigning to synchronized objects in the same synchronized block. 23 | synchronized (mutex) { 24 | mutex_one = new Object(); 25 | doSomething(mutex); 26 | } 27 | } 28 | // {/fact} 29 | 30 | private void doSomething(Object mutex) { 31 | // do-something 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/java/detectors/resource_leak/ResourceLeak.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.resource_leak; 7 | 8 | import lombok.extern.slf4j.Slf4j; 9 | 10 | import java.nio.file.Files; 11 | import java.nio.file.Path; 12 | import java.util.List; 13 | import java.util.stream.Collectors; 14 | import java.util.stream.Stream; 15 | 16 | @Slf4j 17 | public class ResourceLeak { 18 | // {fact rule=resource-leak@v1.0 defects=1} 19 | public List autoCloseableStreamNoncompliant(final Path path) throws Exception { 20 | final List files; 21 | // Noncompliant: does not close the auto-closeable streams of file system objects. 22 | Stream pathStream = Files.walk(path); 23 | files = pathStream.filter(p -> Files.isRegularFile(p)) 24 | .map(path::relativize) 25 | .collect(Collectors.toList()); 26 | log.info("Relativized files: {}", files); 27 | return files; 28 | } 29 | // {/fact} 30 | 31 | // {fact rule=resource-leak@v1.0 defects=0} 32 | public List autoCloseableStreamCompliant(final Path path) throws Exception { 33 | final List files; 34 | // Compliant: the try-with-resources block auto-closes any auto-closeable streams when done. 35 | try (Stream pathStream = Files.walk(path)) { 36 | files = pathStream.filter(p -> Files.isRegularFile(p)) 37 | .map(path::relativize) 38 | .collect(Collectors.toList()); 39 | } 40 | log.info("Relativized files: {}", files); 41 | return files; 42 | } 43 | // {/fact} 44 | } 45 | -------------------------------------------------------------------------------- /src/java/detectors/s3_object_metadata_content_length_check/S3ObjectMetadataContentLengthCheck.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.s3_object_metadata_content_length_check; 7 | 8 | import java.io.File; 9 | import java.io.FileInputStream; 10 | import java.io.FileNotFoundException; 11 | import com.amazonaws.services.s3.AmazonS3; 12 | import com.amazonaws.services.s3.model.ObjectMetadata; 13 | import com.amazonaws.util.IOUtils; 14 | 15 | public class S3ObjectMetadataContentLengthCheck { 16 | 17 | // {fact rule=s3-object-metadata-content-length-check@v1.0 defects=1} 18 | public void s3PutOjectFromStreamNoncompliant(AmazonS3 s3Client, File inputFile) throws FileNotFoundException { 19 | String s3Bucket = "sample-bucket"; 20 | FileInputStream inputStream = null; 21 | try { 22 | inputStream = new FileInputStream(inputFile); 23 | ObjectMetadata metadata = new ObjectMetadata(); 24 | // Noncompliant: puts object from stream without specifying the content length of the stream. 25 | s3Client.putObject(s3Bucket, inputFile.getName(), inputStream, metadata); 26 | } finally { 27 | IOUtils.closeQuietly(inputStream, null); 28 | } 29 | } 30 | // {/fact} 31 | 32 | // {fact rule=s3-object-metadata-content-length-check@v1.0 defects=0} 33 | public void s3PutOjectFromStreamCompliant(AmazonS3 s3Client, File inputFile) throws FileNotFoundException { 34 | String s3Bucket = "sample-bucket"; 35 | FileInputStream inputStream = null; 36 | try { 37 | inputStream = new FileInputStream(inputFile); 38 | ObjectMetadata metadata = new ObjectMetadata(); 39 | // Compliant: specifies the content length of the stream. 40 | metadata.setContentLength(inputFile.length()); 41 | s3Client.putObject(s3Bucket, inputFile.getName(), inputStream, metadata); 42 | } finally { 43 | IOUtils.closeQuietly(inputStream, null); 44 | } 45 | } 46 | // {/fact} 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/java/detectors/s3_object_user_metadata_key_case_sensitivity/S3ObjectUserMetadataKeyCaseSensitivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.s3_object_user_metadata_key_case_sensitivity; 7 | 8 | import com.amazonaws.services.s3.model.ObjectMetadata; 9 | 10 | public class S3ObjectUserMetadataKeyCaseSensitivity { 11 | 12 | // {fact rule=s3-object-user-metadata-key-case-sensitivity@v1.0 defects=1} 13 | public void getUserMetaDataNoncompliant(ObjectMetadata objectMetadata) { 14 | // Noncompliant: the metadata key contains an uppercase letter. 15 | objectMetadata.getUserMetaDataOf("Key"); 16 | } 17 | // {/fact} 18 | 19 | // {fact rule=s3-object-user-metadata-key-case-sensitivity@v1.0 defects=0} 20 | public void getUserMetaDataCompliant(ObjectMetadata objectMetadata) { 21 | // Compliant: the metadata key only contains lowercase letters. 22 | objectMetadata.getUserMetaDataOf("key"); 23 | } 24 | // {/fact} 25 | } 26 | -------------------------------------------------------------------------------- /src/java/detectors/s3_verify_bucket_owner/S3VerifyBucketOwner.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.s3_verify_bucket_owner; 7 | 8 | import software.amazon.awssdk.services.s3.S3Client; 9 | import software.amazon.awssdk.services.s3.model.PutObjectRequest; 10 | import java.nio.file.Path; 11 | import java.nio.file.Paths; 12 | 13 | 14 | public class S3VerifyBucketOwner { 15 | // {fact rule=s3-verify-bucket-owner@v1.0 defects=1} 16 | public void putObjectNoncompliant() { 17 | S3Client s3Client = S3Client.create(); 18 | // Noncompliant: the account that owns the bucket is not specified in the request. 19 | PutObjectRequest request = PutObjectRequest.builder() 20 | .bucket("PUT-EXAMPLE-BUCKET") 21 | .key("example-key") 22 | .build(); 23 | Path path = Paths.get("put_file.txt"); 24 | s3Client.putObject(request, path); 25 | } 26 | // {/fact} 27 | 28 | // {fact rule=s3-verify-bucket-owner@v1.0 defects=0} 29 | public void putObjectCompliant() { 30 | S3Client s3Client = S3Client.create(); 31 | // Compliant: the account that owns the bucket is specified in the request. 32 | PutObjectRequest request = PutObjectRequest.builder() 33 | .bucket("PUT-EXAMPLE-BUCKET") 34 | .key("example-key") 35 | .expectedBucketOwner("111122223333") 36 | .build(); 37 | Path path = Paths.get("put_file.txt"); 38 | s3Client.putObject(request, path); 39 | } 40 | // {/fact} 41 | } 42 | -------------------------------------------------------------------------------- /src/java/detectors/sensitive_information_leak/SensitiveInformationLeak.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.sensitive_information_leak; 7 | 8 | import lombok.extern.slf4j.Slf4j; 9 | import java.util.Map; 10 | 11 | @Slf4j 12 | public class SensitiveInformationLeak { 13 | // {fact rule=sensitive-information-leak@v1.0 defects=1} 14 | public void processResponseNoncompliant(Map response) { 15 | // Noncompliant: logs sensitive data without redaction resulting in a possible sensitive information leak. 16 | final String name = response.get("Name"); 17 | String redacted = RedactionUtil.redact(name); 18 | log.info(name); 19 | } 20 | // {/fact} 21 | 22 | // {fact rule=sensitive-information-leak@v1.0 defects=0} 23 | public void processResponseCompliant(Map response) { 24 | final String name = response.get("Name"); 25 | String redacted = RedactionUtil.redact(name); 26 | // Compliant: sensitive data is passed through redaction before logging, preventing possible sensitive information leak. 27 | log.info(redacted); 28 | } 29 | // {/fact} 30 | 31 | static class RedactionUtil { 32 | 33 | static String redact(String name) { 34 | return name.replaceAll("[^a-zA-Z]", ""); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/java/detectors/session_fixation/SessionFixation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.session_fixation; 7 | 8 | import org.springframework.security.config.annotation.web.configurers.SessionManagementConfigurer; 9 | 10 | public class SessionFixation { 11 | 12 | // {fact rule=session-fixation@v1.0 defects=1} 13 | public Object sessionFixationConfigurerNoncompliant(SessionManagementConfigurer.SessionFixationConfigurer sessionFixationConfigurer) { 14 | // Noncompliant: session fixation protection is disabled. 15 | return sessionFixationConfigurer.none(); 16 | } 17 | // {/fact} 18 | 19 | // {fact rule=session-fixation@v1.0 defects=0} 20 | public Object sessionFixationConfigurerCompliant(SessionManagementConfigurer.SessionFixationConfigurer sessionFixationConfigurer) { 21 | // Compliant: session fixation protection is enabled. 22 | return sessionFixationConfigurer.migrateSession(); 23 | } 24 | // {/fact} 25 | } 26 | -------------------------------------------------------------------------------- /src/java/detectors/simple_date_format_time_zone/SimpleDateFormatTimeZone.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.simple_date_format_time_zone; 7 | 8 | import java.util.Date; 9 | import java.text.SimpleDateFormat; 10 | 11 | public class SimpleDateFormatTimeZone { 12 | // {fact rule=simple-date-format-time-zone@v1.0 defects=1} 13 | void setTimezoneNoncompliant() { 14 | // Noncompliant: does not set the timezone while using a 'SimpleDateFormat' object. 15 | doSomething(new SimpleDateFormat("yyyy-MM-dd").format(new Date())); 16 | } 17 | // {/fact} 18 | 19 | // {fact rule=simple-date-format-time-zone@v1.0 defects=0} 20 | void setTimezoneCompliant() { 21 | // Compliant: sets the timezone while using a 'SimpleDateFormat' object. 22 | doSomething(new SimpleDateFormat("yyyy-MM-dd'Z'").format(new Date())); 23 | } 24 | // {/fact} 25 | 26 | void doSomething(String date) { 27 | // do-something 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/java/detectors/simplifiable_code/SimplifiableCode.java: -------------------------------------------------------------------------------- 1 | package rules.simplifiable_code; 2 | 3 | import android.os.Parcel; 4 | import com.google.common.reflect.TypeToken; 5 | import com.google.gson.Gson; 6 | import com.google.gson.JsonArray; 7 | import com.google.gson.JsonElement; 8 | import com.google.gson.JsonObject; 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | import stubs.Item; 13 | 14 | class SimplifiableCode { 15 | 16 | Gson gson; 17 | 18 | // {fact rule=simplifiable-code@v1.0 defects=1} 19 | public List getItemKeysNonCompliant(JsonObject message) { 20 | JsonArray items = message.getAsJsonArray("key"); 21 | List list = new ArrayList<>(); 22 | // Noncompliant: JsonArray is deserialized to construct a list of items by iterating in a loop. 23 | for (JsonElement item : items) { 24 | list.add(gson.fromJson(item, String.class)); 25 | } 26 | return list; 27 | } 28 | // {/fact} 29 | 30 | // {fact rule=simplifiable-code@v1.0 defects=0} 31 | public List getItemKeysCompliant(JsonObject message) { 32 | JsonArray items = message.getAsJsonArray("key"); 33 | // Compliant: JsonArray is deserialized to construct a list of items without iterating in a loop. 34 | return gson.fromJson(items, new TypeToken>(){}.getType()); 35 | } 36 | // {/fact} 37 | 38 | // {fact rule=simplifiable-code@v1.0 defects=1} 39 | public String getItemNonCompliant(Parcel input) { 40 | try { 41 | // Noncompliant: output of readValue is type cast to String. 42 | return (String) input.readValue(String.class.getClassLoader()); 43 | } catch (Exception ex) { 44 | ex.printStackTrace(); 45 | return null; 46 | } 47 | } 48 | // {/fact} 49 | 50 | // {fact rule=simplifiable-code@v1.0 defects=0} 51 | public String getItemCompliant(Parcel input) { 52 | try { 53 | // Compliant: readParcelable is used to read the Parcel input, which does not require an explicit type cast. 54 | return input.readParcelable(String.class.getClassLoader()); 55 | } catch (Exception ex) { 56 | ex.printStackTrace(); 57 | return null; 58 | } 59 | } 60 | // {/fact} 61 | } 62 | -------------------------------------------------------------------------------- /src/java/detectors/sql_injection/SqlInjection.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.sql_injection; 7 | 8 | import javax.servlet.http.HttpServletRequest; 9 | 10 | public class SqlInjection { 11 | 12 | // {fact rule=sql-injection@v1.0 defects=1} 13 | public void executeSqlStatementNoncompliant(HttpServletRequest request, java.sql.Connection connection) { 14 | final String favoriteColor = request.getParameter("favoriteColor"); 15 | try { 16 | String sql = "SELECT * FROM people WHERE favorite_color='" + favoriteColor + "'"; 17 | java.sql.Statement statement = connection.createStatement(); 18 | // Noncompliant: user-given input is not sanitized before use. 19 | statement.execute(sql); 20 | } catch (java.sql.SQLException e) { 21 | throw new RuntimeException(e); 22 | } 23 | } 24 | // {/fact} 25 | 26 | // {fact rule=sql-injection@v1.0 defects=0} 27 | public void executeSqlStatementCompliant(HttpServletRequest request, java.sql.Connection connection) { 28 | final String favoriteColor = request.getParameter("favoriteColor"); 29 | // Compliant: user-given input is sanitized before use. 30 | if (!favoriteColor.matches("[a-z]+")) { 31 | throw new IllegalArgumentException(); 32 | } 33 | try { 34 | String sql = "SELECT * FROM people WHERE favorite_color='" + favoriteColor + "'"; 35 | java.sql.Statement statement = connection.createStatement(); 36 | statement.execute(sql); 37 | } catch (java.sql.SQLException e) { 38 | throw new RuntimeException(e); 39 | } 40 | } 41 | // {/fact} 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/java/detectors/stream_anymatch_vs_findfirst/StreamAnymatchVsFindfirst.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.stream_anymatch_vs_findfirst; 7 | 8 | import java.util.Collection; 9 | import java.util.Objects; 10 | 11 | public class StreamAnymatchVsFindfirst { 12 | Collection col; 13 | 14 | // {fact rule=stream-anymatch-vs-findfirst@v1.0 defects=1} 15 | boolean streamCollectionNoncompliant(final Collection col) { 16 | // Noncompliant: uses a chain of "filter", "findFirst" and "isPresent" stream methods over anyMatch. 17 | return col.stream() 18 | .filter(Objects::isNull) 19 | .findFirst() 20 | .isPresent(); 21 | } 22 | // {/fact} 23 | 24 | // {fact rule=stream-anymatch-vs-findfirst@v1.0 defects=0} 25 | boolean streamCollectionCompliant(final Collection col) { 26 | // Compliant: uses anyMatch stream method over the others which is more readable and convenient. 27 | return col.stream().anyMatch(Objects::isNull); 28 | } 29 | // {/fact} 30 | } 31 | -------------------------------------------------------------------------------- /src/java/detectors/stream_min_max_vs_sort/StreamMinMaxVsSort.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.stream_min_max_vs_sort; 7 | 8 | import java.util.Collection; 9 | import java.util.Optional; 10 | 11 | public class StreamMinMaxVsSort { 12 | // {fact rule=stream-min-max-vs-sort@v1.0 defects=1} 13 | Optional streamSortThenFindFirstNoncompliant(final Collection col) { 14 | // Noncompliant: uses sorted and findFirst over min, max stream methods. 15 | return col.stream() 16 | .sorted() 17 | .findFirst(); 18 | } 19 | // {/fact} 20 | 21 | // {fact rule=stream-min-max-vs-sort@v1.0 defects=0} 22 | Optional MinCompliant(final Collection col) { 23 | // Compliant: uses min, max methods over sorted and findFirst stream methods. 24 | return col.stream().min(String::compareTo); 25 | } 26 | // {/fact} 27 | } 28 | -------------------------------------------------------------------------------- /src/java/detectors/string_equality_check/StringEqualityCheck.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.string_equality_check; 7 | 8 | public class StringEqualityCheck { 9 | 10 | // {fact rule=string-equality-check@v1.0 defects=1} 11 | public void stringEqualityCheckNoncompliant(String string1, String string2) { 12 | // Noncompliant: the == operator doesn't compare the contents of the strings. 13 | if(string1 == string2) { 14 | System.out.println("The strings are equal."); 15 | } 16 | } 17 | // {/fact} 18 | 19 | // {fact rule=string-equality-check@v1.0 defects=0} 20 | public void stringEqualityCheckCompliant(String string1, String string2) { 21 | // Compliant: the equals() method compares the contents of the strings. 22 | if(string1.equals(string2)) { 23 | System.out.println("The strings are equal."); 24 | } 25 | } 26 | // {/fact} 27 | } 28 | -------------------------------------------------------------------------------- /src/java/detectors/string_format_arguments/StringFormatArguments.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.string_format_arguments; 7 | 8 | import lombok.extern.slf4j.Slf4j; 9 | import java.io.File; 10 | 11 | @Slf4j 12 | public class StringFormatArguments { 13 | // {fact rule=string-format-arguments@v1.0 defects=1} 14 | void formatStringNoncompliant(final File file) { 15 | final long length = file.length(); 16 | // Noncompliant: avoids using the correct format strings for their argument types. 17 | final String s = String.format("File length is %s", length); 18 | log.info(s); 19 | } 20 | // {/fact} 21 | 22 | // {fact rule=string-format-arguments@v1.0 defects=0} 23 | void formatStringCompliant(final File file) { 24 | final long length = file.length(); 25 | // Compliant: uses the correct format strings for their argument types. 26 | final String s = String.format("File length is %d", length); 27 | log.info(s); 28 | } 29 | // {/fact} 30 | } 31 | -------------------------------------------------------------------------------- /src/java/detectors/sudden_service_shutdown/SuddenServiceShutdown.java: -------------------------------------------------------------------------------- 1 | package rules.sudden_service_shutdown; 2 | 3 | import java.util.concurrent.ExecutorService; 4 | import java.util.concurrent.TimeUnit; 5 | import static java.util.concurrent.TimeUnit.SECONDS; 6 | 7 | class SuddenServiceShutdown { 8 | 9 | // {fact rule=sudden-service-shutdown@v1.0 defects=1} 10 | void shutdownNonCompliant(ExecutorService executorService) throws InterruptedException { 11 | if (executorService != null) { 12 | // Noncompliant: shutdownNow is called which suddenly shuts down executorService. 13 | executorService.shutdownNow(); 14 | } 15 | } 16 | // {/fact} 17 | 18 | // {fact rule=sudden-service-shutdown@v1.0 defects=0} 19 | void shutdownCompliant(ExecutorService executorService) throws InterruptedException { 20 | if (executorService != null) { 21 | // Compliant: attempts graceful shutdown before doing so forcefully. 22 | executorService.shutdown(); 23 | if (!executorService.awaitTermination(10, TimeUnit.SECONDS)) { 24 | throw new IllegalStateException("Timed out while waiting for executing threads to terminate"); 25 | } 26 | executorService.shutdownNow(); 27 | } 28 | } 29 | // {/fact} 30 | } 31 | -------------------------------------------------------------------------------- /src/java/detectors/sync_metric_publish/SyncMetricPublishCompliant.java: -------------------------------------------------------------------------------- 1 | package detectors.sync_metric_publish; 2 | 3 | import com.amazonaws.services.cloudwatch.model.MetricDatum; 4 | import com.amazonaws.services.cloudwatch.model.StandardUnit; 5 | import com.amazonaws.services.lambda.runtime.Context; 6 | import com.amazonaws.services.lambda.runtime.LambdaLogger; 7 | import com.amazonaws.services.lambda.runtime.RequestHandler; 8 | import com.amazonaws.services.lambda.runtime.events.ScheduledEvent; 9 | 10 | // {fact rule=sync-metric-publish@v1.0 defects=0} 11 | public class SyncMetricPublishCompliant implements RequestHandler { 12 | 13 | public SyncMetricPublishCompliant() { 14 | // Initialize class members here. 15 | } 16 | 17 | @Override 18 | public Void handleRequest(ScheduledEvent scheduledEvent, Context context) { 19 | LambdaLogger logger = context.getLogger(); 20 | final long startTime = System.currentTimeMillis(); 21 | doSomething(scheduledEvent, context); 22 | final long endTime = System.currentTimeMillis(); 23 | final long timeElapsed = endTime - startTime; 24 | MetricDatum metricDatum = new MetricDatum().withMetricName("TIME_ELAPSED") 25 | .withUnit(StandardUnit.Milliseconds).withValue((double) timeElapsed); 26 | // Compliant: logs the metrics for further postprocessing outside the Lambda. 27 | logger.log("Metrics: " + metricDatum); 28 | return null; 29 | } 30 | 31 | private void doSomething(ScheduledEvent scheduledEvent, Context context) { 32 | // Placeholder for code. 33 | } 34 | } 35 | // {/fact} 36 | -------------------------------------------------------------------------------- /src/java/detectors/sync_metric_publish/SyncMetricPublishNoncompliant.java: -------------------------------------------------------------------------------- 1 | package detectors.sync_metric_publish; 2 | 3 | import com.amazonaws.regions.Regions; 4 | import com.amazonaws.services.cloudwatch.AmazonCloudWatch; 5 | import com.amazonaws.services.cloudwatch.AmazonCloudWatchClientBuilder; 6 | import com.amazonaws.services.cloudwatch.model.MetricDatum; 7 | import com.amazonaws.services.cloudwatch.model.PutMetricDataRequest; 8 | import com.amazonaws.services.cloudwatch.model.StandardUnit; 9 | import com.amazonaws.services.lambda.runtime.Context; 10 | import com.amazonaws.services.lambda.runtime.RequestHandler; 11 | import com.amazonaws.services.lambda.runtime.events.ScheduledEvent; 12 | 13 | // {fact rule=sync-metric-publish@v1.0 defects=1} 14 | public class SyncMetricPublishNoncompliant implements RequestHandler { 15 | 16 | AmazonCloudWatch cloudwatch; 17 | 18 | public SyncMetricPublishNoncompliant() { 19 | cloudwatch = AmazonCloudWatchClientBuilder.standard().withRegion(Regions.US_WEST_2.toString()).build(); 20 | } 21 | 22 | @Override 23 | public Void handleRequest(ScheduledEvent scheduledEvent, Context context) { 24 | final long startTime = System.currentTimeMillis(); 25 | doSomething(scheduledEvent, context); 26 | final long endTime = System.currentTimeMillis(); 27 | final long timeElapsed = endTime - startTime; 28 | PutMetricDataRequest putMetricDataRequest = new PutMetricDataRequest(); 29 | MetricDatum metricDatum = new MetricDatum().withMetricName("TIME_ELAPSED") 30 | .withUnit(StandardUnit.Milliseconds).withValue((double) timeElapsed); 31 | putMetricDataRequest.withNamespace("EXAMPLE_NAMESPACE").withMetricData(metricDatum); 32 | // Noncompliant: uses CloudWatch to synchronically publish metrics from inside a Lambda. 33 | cloudwatch.putMetricData(putMetricDataRequest); 34 | return null; 35 | } 36 | 37 | private void doSomething(ScheduledEvent scheduledEvent, Context context) { 38 | // Placeholder for code. 39 | } 40 | } 41 | // {/fact} 42 | -------------------------------------------------------------------------------- /src/java/detectors/thread_safety_class_violations/ThreadSafetyClassViolationsCompliant.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.thread_safety_class_violations; 7 | 8 | import com.amazonaws.annotation.ThreadSafe; 9 | import java.util.HashMap; 10 | import stubs.FileInfo; 11 | 12 | // {fact rule=thread-safety-class-violations@v1.0 defects=0} 13 | @ThreadSafe 14 | public class ThreadSafetyClassViolationsCompliant { 15 | 16 | private HashMap fileInfoMap = new HashMap(); 17 | 18 | // Compliant: all methods are thread-safe. 19 | 20 | public synchronized void reset() { 21 | fileInfoMap.clear(); 22 | } 23 | 24 | public synchronized void addFileInfo(String fileName, long fileSize) { 25 | FileInfo fileInfo = new FileInfo(fileName, fileSize); 26 | fileInfoMap.put(fileName, fileInfo); 27 | } 28 | 29 | public synchronized FileInfo getFileInfoSync(String fileName) { 30 | return fileInfoMap.get(fileName); 31 | } 32 | } 33 | // {/fact} 34 | -------------------------------------------------------------------------------- /src/java/detectors/thread_safety_class_violations/ThreadSafetyClassViolationsNoncompliant.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.thread_safety_class_violations; 7 | import com.amazonaws.annotation.ThreadSafe; 8 | import stubs.FileInfo; 9 | 10 | import java.util.HashMap; 11 | 12 | // {fact rule=thread-safety-class-violations@v1.0 defects=1} 13 | @ThreadSafe 14 | public class ThreadSafetyClassViolationsNoncompliant { 15 | 16 | private HashMap fileInfoMap = new HashMap(); 17 | 18 | public synchronized void reset() { 19 | fileInfoMap.clear(); 20 | } 21 | 22 | public synchronized void addFileInfo(String fileName, long fileSize) { 23 | FileInfo fileInfo = new FileInfo(fileName, fileSize); 24 | fileInfoMap.put(fileName, fileInfo); 25 | } 26 | 27 | // Noncompliant: the method doesn't protect the parallel use of map. 28 | public FileInfo getFileInfo(String fileName) { 29 | return fileInfoMap.get(fileName); 30 | } 31 | 32 | public synchronized FileInfo getFileInfoSync(String fileName) { 33 | return fileInfoMap.get(fileName); 34 | } 35 | } 36 | // {/fact} 37 | -------------------------------------------------------------------------------- /src/java/detectors/thread_safety_violation/ThreadSafetyViolationCompliant.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.thread_safety_violation; 7 | 8 | import javax.annotation.concurrent.ThreadSafe; 9 | import java.util.concurrent.locks.ReentrantLock; 10 | 11 | // {fact rule=thread-safety-violation@v1.0 defects=0} 12 | class PropertiesCompliant { 13 | private int parameter = 0; 14 | 15 | public int getParameter() { 16 | return parameter; 17 | } 18 | 19 | public void setParameter(int number) { 20 | parameter = number; 21 | } 22 | } 23 | 24 | @ThreadSafe 25 | class ThreadSafetyViolationCompliant { 26 | private final PropertiesCompliant properties = new PropertiesCompliant(); 27 | private final ReentrantLock lock = new ReentrantLock(); 28 | 29 | public void syncReadCallOutsideCompliant(int i) { 30 | // Compliant: follows thread safety by indirectly reading with synchronization. 31 | lock.lock(); 32 | if (properties.getParameter() > i) { 33 | properties.setParameter(i); 34 | } 35 | lock.unlock(); 36 | } 37 | } 38 | // {/fact} 39 | 40 | -------------------------------------------------------------------------------- /src/java/detectors/thread_safety_violation/ThreadSafetyViolationNoncompliant.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.thread_safety_violation; 7 | 8 | import javax.annotation.concurrent.ThreadSafe; 9 | import java.util.concurrent.locks.ReentrantLock; 10 | 11 | // {fact rule=thread-safety-violation@v1.0 defects=1} 12 | class PropertiesNoncompliant { 13 | 14 | private int parameter = 0; 15 | 16 | public int getParameter() { 17 | return parameter; 18 | } 19 | 20 | public void setParameter(int number) { 21 | parameter = number; 22 | } 23 | } 24 | 25 | @ThreadSafe 26 | class ThreadSafetyViolationNoncompliant { 27 | private final PropertiesNoncompliant properties = new PropertiesNoncompliant(); 28 | private final ReentrantLock lock = new ReentrantLock(); 29 | 30 | public void syncReadCallOutsideNoncompliant(int i) { 31 | // Noncompliant: violates thread safety by indirectly reading without synchronization. 32 | if (properties.getParameter() > i) { 33 | lock.lock(); 34 | properties.setParameter(i); 35 | lock.unlock(); 36 | } 37 | } 38 | } 39 | // {/fact} 40 | 41 | -------------------------------------------------------------------------------- /src/java/detectors/throw_exception_with_trace/ThrowExceptionWithTrace.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.throw_exception_with_trace; 7 | 8 | public class ThrowExceptionWithTrace { 9 | 10 | // {fact rule=throw-exception-with-trace@v1.0 defects=1} 11 | public void throwExceptionWithTraceNoncompliant() throws Exception { 12 | try { 13 | doSomething(); 14 | } catch (Exception e) { 15 | // Noncompliant: the new exception only has the message from the original exception. 16 | throw new Exception("Error: " + e.getMessage()); 17 | } 18 | } 19 | // {/fact} 20 | 21 | // {fact rule=throw-exception-with-trace@v1.0 defects=0} 22 | public void throwExceptionWithTraceCompliant() throws Exception { 23 | try { 24 | doSomething(); 25 | } catch (Exception e) { 26 | // Compliant: the new exception contains the original exception. 27 | throw new Exception("Error: " + e.getMessage(), e); 28 | } 29 | } 30 | // {/fact} 31 | 32 | private void doSomething() { 33 | // Placeholder for code. 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/java/detectors/ui_thread_starvation/UiThreadStarvation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.ui_thread_starvation; 7 | 8 | import android.support.annotation.UiThread; 9 | import java.util.concurrent.CountDownLatch; 10 | 11 | public class UiThreadStarvation { 12 | // {fact rule=ui-thread-starvation@v1.0 defects=1} 13 | @UiThread 14 | void awaitOnMainNoncompliant(CountDownLatch latch) throws InterruptedException { 15 | Object main = new Object(); 16 | // Noncompliant: blocks calls in a user interface thread. 17 | latch.await(); 18 | } 19 | // {/fact} 20 | 21 | // {fact rule=ui-thread-starvation@v1.0 defects=0} 22 | @UiThread 23 | void awaitOnMainCompliant(CountDownLatch latch) throws InterruptedException { 24 | // Compliant: avoids blocking calls on user interface thread. 25 | latch.countDown(); 26 | } 27 | // {/fact} 28 | } 29 | -------------------------------------------------------------------------------- /src/java/detectors/unspecified_default_value/UnspecifiedDefaultValue.java: -------------------------------------------------------------------------------- 1 | package rules.unspecified_default_value; 2 | 3 | import io.grpc.Channel; 4 | import io.grpc.netty.NegotiationType; 5 | import io.grpc.netty.NettyChannelBuilder; 6 | import java.net.URI; 7 | 8 | class UnspecifiedDefaultValue { 9 | 10 | // {fact rule=unspecified-default-value@v1.0 defects=1} 11 | private Channel createChannelNonCompliant(URI uri) { 12 | // Noncompliant: default value for the port number is not specified. 13 | return NettyChannelBuilder.forAddress(uri.getHost(), uri.getPort()) 14 | .negotiationType(NegotiationType.PLAINTEXT) 15 | .build(); 16 | } 17 | // {/fact} 18 | 19 | // {fact rule=unspecified-default-value@v1.0 defects=0} 20 | private Channel createChannelCompliant(URI uri) { 21 | int port = uri.getPort(); 22 | // Compliant: default value for the port number is specified. 23 | if (port == -1) { 24 | port = 11984; 25 | } 26 | return NettyChannelBuilder.forAddress(uri.getHost(), port) 27 | .negotiationType(NegotiationType.PLAINTEXT) 28 | .build(); 29 | } 30 | // {/fact} 31 | } 32 | -------------------------------------------------------------------------------- /src/java/detectors/untrusted_ami_images/UntrustedAmiImages.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.untrusted_ami_images; 7 | 8 | import com.amazonaws.services.ec2.AmazonEC2; 9 | import com.amazonaws.services.ec2.model.DescribeImagesRequest; 10 | import com.amazonaws.services.ec2.model.DescribeImagesResult; 11 | import com.amazonaws.services.ec2.model.Filter; 12 | import java.util.Arrays; 13 | 14 | public class UntrustedAmiImages { 15 | 16 | // {fact rule=untrusted-ami-images@v1.0 defects=1} 17 | public void describeImagesNoncompliant(AmazonEC2 client) { 18 | final String imageName = "sample_image_name"; 19 | final Filter filter = new Filter("name").withValues(imageName); 20 | // Noncompliant: images are filtered using name only. 21 | DescribeImagesResult result = 22 | client.describeImages(new DescribeImagesRequest().withFilters(filter)); 23 | } 24 | // {/fact} 25 | 26 | // {fact rule=untrusted-ami-images@v1.0 defects=0} 27 | public void describeImagesCompliant(AmazonEC2 client) { 28 | final String imageName = "sample_image_name"; 29 | final String imageOwner = "sample_image_owner"; 30 | final Filter nameFilter = new Filter("name").withValues(imageName); 31 | final Filter ownerFilter = new Filter("owner-alias").withValues(imageOwner); 32 | // Compliant: images are filtered using name and owner. 33 | DescribeImagesResult result = 34 | client.describeImages(new DescribeImagesRequest().withFilters(Arrays.asList(nameFilter, ownerFilter))); 35 | } 36 | // {/fact} 37 | } 38 | -------------------------------------------------------------------------------- /src/java/detectors/untrusted_data_in_decision/UntrustedDataInDecision.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.untrusted_data_in_decision; 7 | 8 | import javax.servlet.http.HttpServletRequest; 9 | 10 | public class UntrustedDataInDecision { 11 | 12 | // {fact rule=untrusted-data-in-decision@v1.0 defects=1} 13 | public void logSessionIdNoncompliant(HttpServletRequest request) { 14 | final String sessionId = request.getRequestedSessionId(); 15 | // Noncompliant: user-supplied session ID is used to make a decision. 16 | if (sessionId != null && sessionId.equals("ImportantSession")) { 17 | System.out.println("Client-provided session ID: " + sessionId + " is important"); 18 | } 19 | } 20 | // {/fact} 21 | 22 | // {fact rule=untrusted-data-in-decision@v1.0 defects=0} 23 | public void logSessionIdCompliant(HttpServletRequest request) { 24 | // Compliant: user-supplied session ID is not used to make decisions. 25 | System.out.println("Client-provided session ID: " + request.getRequestedSessionId()); 26 | } 27 | // {/fact} 28 | } 29 | -------------------------------------------------------------------------------- /src/java/detectors/untrusted_deserialization/UntrustedDeserialization.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.untrusted_deserialization; 7 | 8 | import com.fasterxml.jackson.databind.ObjectMapper; 9 | 10 | import java.io.File; 11 | import java.util.List; 12 | 13 | public class UntrustedDeserialization { 14 | // {fact rule=untrusted-deserialization@v1.0 defects=1} 15 | public List ObjectMapperNoncompliant(final File input) throws Exception { 16 | final ObjectMapper mapper = new ObjectMapper(); 17 | // Noncompliant: enabling default typing can introduce a remote code execution vulnerability. 18 | mapper.enableDefaultTyping(); 19 | return mapper.readValue(input, List.class); 20 | } 21 | // {/fact} 22 | 23 | // {fact rule=untrusted-deserialization@v1.0 defects=0} 24 | public List ObjectMapperCompliant(final File input) throws Exception { 25 | final ObjectMapper mapper = new ObjectMapper(); 26 | // Compliant: disabling default typing prevents the vulnerability. 27 | mapper.deactivateDefaultTyping(); 28 | return mapper.readValue(input, List.class); 29 | } 30 | // {/fact} 31 | } 32 | -------------------------------------------------------------------------------- /src/java/detectors/weak_obfuscation_of_request/WeakObfuscationOfRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.weak_obfuscation_of_request; 7 | 8 | import org.apache.http.client.methods.HttpPost; 9 | 10 | import java.net.URISyntaxException; 11 | import java.net.URL; 12 | import java.util.Base64; 13 | 14 | public class WeakObfuscationOfRequest { 15 | // {fact rule=weak-obfuscation-of-request@v1.0 defects=1} 16 | public void httpAuthenticationNoncompliant(final URL url, final String password) throws URISyntaxException { 17 | final String encoding = Base64.getEncoder().encode(password.getBytes()).toString(); 18 | HttpPost httppost = new HttpPost(url.toURI()); 19 | // Noncompliant: uses HTTP Basic Authentication. 20 | httppost.setHeader("Authorization", "Basic " + encoding); 21 | } 22 | // {/fact} 23 | } 24 | -------------------------------------------------------------------------------- /src/java/detectors/weak_random_number_generation/WeakRandomNumberGeneration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.weak_random_number_generation; 7 | 8 | import java.security.SecureRandom; 9 | 10 | public class WeakRandomNumberGeneration { 11 | // {fact rule=weak-random-number-generation@v1.0 defects=1} 12 | static void secureRandomSpecificAlgorithmNoncompliant() throws Exception { 13 | final String ALGORITHM_NAME = "DES"; 14 | // Noncompliant: one specific algorithm is requested. 15 | SecureRandom generator = SecureRandom.getInstance(ALGORITHM_NAME); 16 | System.out.println(generator.nextInt()); 17 | } 18 | // {/fact} 19 | 20 | // {fact rule=weak-random-number-generation@v1.0 defects=0} 21 | static void secureRandomDefaultCompliant() throws Exception { 22 | // Compliant: no specific algorithm is requested. 23 | SecureRandom generator = new SecureRandom(); 24 | System.out.println(generator.nextInt()); 25 | } 26 | // {/fact} 27 | } 28 | -------------------------------------------------------------------------------- /src/java/detectors/xml_external_entity/XmlExternalEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.xml_external_entity; 7 | 8 | import javax.xml.parsers.DocumentBuilder; 9 | import javax.xml.parsers.DocumentBuilderFactory; 10 | import javax.xml.parsers.ParserConfigurationException; 11 | import java.io.InputStream; 12 | 13 | public class XmlExternalEntity { 14 | 15 | // {fact rule=xml-external-entity@v1.0 defects=1} 16 | public DocumentBuilder createDocumentBuilderNoncompliant(InputStream inputStream) throws Exception { 17 | DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 18 | factory.setValidating(true); 19 | factory.setIgnoringElementContentWhitespace(true); 20 | // Noncompliant: not configured to handle external entities. 21 | DocumentBuilder builder = factory.newDocumentBuilder(); 22 | builder.parse(inputStream); 23 | return builder; 24 | } 25 | // {/fact} 26 | 27 | // {fact rule=xml-external-entity@v1.0 defects=0} 28 | public DocumentBuilder createDocumentBuilderCompliant(InputStream inputStream) throws Exception { 29 | DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 30 | factory.setValidating(true); 31 | factory.setIgnoringElementContentWhitespace(true); 32 | // Compliant: configured to disable external entities. 33 | factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); 34 | DocumentBuilder builder = factory.newDocumentBuilder(); 35 | builder.parse(inputStream); 36 | return builder; 37 | } 38 | // {/fact} 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/java/detectors/xpath_injection/XpathInjection.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package detectors.xpath_injection; 7 | 8 | import javax.servlet.http.HttpServletRequest; 9 | import org.w3c.dom.Document; 10 | import javax.xml.xpath.XPath; 11 | import javax.xml.xpath.XPathExpressionException; 12 | 13 | public class XpathInjection { 14 | 15 | // {fact rule=xpath-injection@v1.0 defects=1} 16 | public void evaluateExpressionNoncompliant(HttpServletRequest request, XPath xpath, Document xml) 17 | throws XPathExpressionException { 18 | String employeeID = request.getParameter("employeeID"); 19 | String expression = "/employees/" + employeeID + "/sales/monthly"; 20 | // Noncompliant: evaluating expression built from user-supplied parameter can lead to XPath injection. 21 | xpath.evaluate(expression, xml); 22 | } 23 | // {/fact} 24 | 25 | // {fact rule=xpath-injection@v1.0 defects=0} 26 | public void evaluateExpressionCompliant(HttpServletRequest request, XPath xpath, Document xml) 27 | throws XPathExpressionException { 28 | String employeeID = request.getParameter("employeeID"); 29 | // Compliant: user-supplied parameter is sanitized before its inclusion in the expression. 30 | if (!employeeID.matches("[0-9]+")) { 31 | throw new IllegalArgumentException(); 32 | } 33 | String expression = "/employees/" + employeeID + "/sales/monthly"; 34 | xpath.evaluate(expression, xml); 35 | } 36 | // {/fact} 37 | } 38 | -------------------------------------------------------------------------------- /src/java/stubs/ActivityJobItem.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package stubs; 7 | 8 | import java.util.Map; 9 | 10 | public class ActivityJobItem { 11 | public Map getActivityVideos() { 12 | return null; 13 | } 14 | 15 | public class ActivityVideo { 16 | public Object getVideoStreamArn() { 17 | return null; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/java/stubs/ActivityType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package stubs; 7 | 8 | public class ActivityType { 9 | public static final ActivityType TRAINING = null; 10 | public static final ActivityType EVALUATION = null; 11 | public static final ActivityType FINETUNING = null; 12 | } 13 | -------------------------------------------------------------------------------- /src/java/stubs/DynamoBatchWriteOutputCompliant.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package stubs; 7 | import java.util.List; 8 | 9 | public abstract class DynamoBatchWriteOutputCompliant { 10 | public abstract List mapperCompliant(DynamoDBMapperCollection batch); 11 | } 12 | -------------------------------------------------------------------------------- /src/java/stubs/DynamoBatchWriteOutputNoncompliant.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package stubs; 7 | 8 | public abstract class DynamoBatchWriteOutputNoncompliant { 9 | public abstract void mapperNoncompliant(DynamoDBMapperCollection batch); 10 | } 11 | -------------------------------------------------------------------------------- /src/java/stubs/DynamoDBMapperCollection.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package stubs; 7 | 8 | public class DynamoDBMapperCollection { 9 | 10 | public void clear() { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/java/stubs/EC2Client.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package stubs; 7 | 8 | import com.amazonaws.services.ec2.model.DescribeInstanceStatusRequest; 9 | import com.amazonaws.services.ec2.model.DescribeInstanceStatusResult; 10 | import com.amazonaws.services.ec2.waiters.AmazonEC2Waiters; 11 | 12 | public class EC2Client { 13 | public DescribeInstanceStatusResult describeInstanceStatus(DescribeInstanceStatusRequest withIncludeAllInstances) { 14 | return null; 15 | } 16 | 17 | public AmazonEC2Waiters waiters() { 18 | return null; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/java/stubs/FileInfo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package stubs; 7 | 8 | public class FileInfo { 9 | 10 | private String fileName; 11 | private long fileSize; 12 | 13 | public FileInfo(String fileName, long fileSize) { 14 | this.fileName = fileName; 15 | this.fileSize = fileSize; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/java/stubs/Item.java: -------------------------------------------------------------------------------- 1 | package stubs; 2 | 3 | public interface Item { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /src/java/stubs/ResultClass.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package stubs; 7 | 8 | import java.util.concurrent.TimeoutException; 9 | 10 | public class ResultClass { 11 | public String getResult() throws TimeoutException { 12 | return "pass"; 13 | } 14 | 15 | public boolean connect() { 16 | return true; 17 | } 18 | 19 | public void retry() { 20 | //do something 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/java/stubs/ViewHolder.java: -------------------------------------------------------------------------------- 1 | package stubs; 2 | 3 | import android.view.View; 4 | 5 | public class ViewHolder { 6 | 7 | public ViewHolder(View itemView) { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/java/stubs/evaluationJobDao.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package stubs; 7 | 8 | public class evaluationJobDao { 9 | public static ActivityJobItem loadEvaluationJob(String activityJobArn) { 10 | return null; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/java/stubs/finetuningJobDao.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package stubs; 7 | 8 | public class finetuningJobDao { 9 | public static ActivityJobItem loadFinetuningJob(String activityJobArn) { 10 | return null; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/java/stubs/sqsMetricsClient.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package stubs; 7 | 8 | public class sqsMetricsClient { 9 | public static void changeMessageVisibility(String queueName, String handle, String timeout) { 10 | 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/java/stubs/trainingJobDao.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | 6 | package stubs; 7 | 8 | public class trainingJobDao { 9 | public static ActivityJobItem loadTrainingJob(String activityJobArn) { 10 | return null; 11 | } 12 | } 13 | --------------------------------------------------------------------------------