├── .github ├── steps │ ├── 1-enable-secret-scanning.md │ ├── 2-review-alerts.md │ ├── 3-enable-push-protection.md │ └── x-review.md └── workflows │ ├── 0-start-exercise.yml │ ├── 1-enable-secret-scanning.yml │ ├── 2-review-alerts.yml │ └── 3-enable-push-protection.yml ├── .gitignore ├── LICENSE └── README.md /.github/steps/1-enable-secret-scanning.md: -------------------------------------------------------------------------------- 1 | ## Step 1: Enable Secret Protection 2 | 3 | If you check your email, you probably just got an alert from GitHub with the subject "Possible valid secrets found". Oh no! 😮 4 | 5 | Don't worry! We put some expired credentials in the exercise on purpose since public repositories get secret protection for free. Nice! 🕵️ 6 | 7 | In this step, you will enable secret protection on your repository. After it is enabled, you will add a new credential to see how secret protection identifies the credential and alerts you. 8 | 9 | > [!WARNING] 10 | > If your repository is private, you will need [GitHub Advanced Security](https://docs.github.com/en/enterprise-cloud@latest/get-started/learning-about-github/about-github-advanced-security) to continue. We recommend [changing this exercise repository to public](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/managing-repository-settings/setting-repository-visibility) to enable it. 11 | 12 | ### What is a secret? 13 | 14 | In the our context, a secret (or credential) is a plain-text string, or a pair of strings, that authorizes access a service. Examples could be AWS secret access keys/ID's, Google API keys, or GitHub Personal Access Tokens (PATs). 15 | 16 | The GitHub Docs provides a list of [all supported patterns](https://docs.github.com/en/code-security/secret-scanning/secret-scanning-patterns#supported-secrets). 17 | 18 | ### What is secret protection? 19 | 20 | Secret protection is a powerful tool which allows teams to identify these plain-text credentials, remove them, and create rules to prevent them from being written to GitHub in the first place. 21 | 22 | Secret protection is available **for free for public repositories** on all plans. Enterprises that need secret protection capabilities for private repositories should review [GitHub Advanced Security](https://github.com/security/advanced-security). Not only does it include secret protection, it also provides advanced static analysis, software composition analysis (SCA), and enterprise tools to manage your entire AppSec pipeline and reduce your risk profile. 23 | 24 | ### :keyboard: Activity: Configure secret protection 25 | 26 | 1. In the header of your repository, open **Settings** in a new browser tab. 27 | 28 | 1. In the left navigation, under the **Security** section, select **Advanced Security**. 29 | 30 | 1. Scroll down past the **Code Scanning** and **Dependabot** sections until you find the **Secret Protection** section. 31 | 32 | > 💡 **Tip:** We also have exercises about [code scanning](https://github.com/skills/introduction-to-codeql) and [supply chain protection](https://github.com/skills/secure-repository-supply-chain)! 33 | 34 | 1. Adjust the default configuration to match the below. 35 | 36 | - **Secret Protection:** `enabled` 37 | - **Push Protection:** `disabled` 38 | 39 | Secret protection configuration settings 40 | 41 | ### :keyboard: Activity: Commit a sensitive file 42 | 43 | Now let's (accidentally) commit a sensitive file to see how it works. Don't worry, these are inactive credentials. 44 | 45 | 1. In the header of your repository, click the **Code** tab. 46 | 47 | 1. Above the list of files, click the **Add file** dropdown and select **Create new file**. 48 | 49 | New file button 50 | 51 | 1. Enter the file name `credentials.yml` and copy following **inactive** example credentials into it. 52 | 53 | New file button 54 | 55 | ```yaml 56 | default: 57 | aws_access_key_id: AKIAQYLPMN5HNM4OZ56B 58 | aws_secret_access_key: Rm29CHLQCeaT6V/Rsw3UFWW1/UWQ0lhsWBa3bdca 59 | mongodb: mongodb+srv://svc-admin:kLeioeBne5lsopPf@mergington-high.avocado.mongodb.net 60 | output: json 61 | region: us-east-2 62 | ``` 63 | 64 | 1. In the top right, use the **Commit changes...** button to commit directly to the `main` branch. 65 | 66 | > ❗️ **Important:** Committing to your default branch is not usually a recommended practice. We only do this to simplify the exercise. 67 | 68 | 1. With our credentials file (accidentally) shared, Mona should quickly notice it and prepare the next step. 69 | -------------------------------------------------------------------------------- /.github/steps/2-review-alerts.md: -------------------------------------------------------------------------------- 1 | ## Step 2: Review and close secret scanning alerts 2 | 3 | In the last step, you enabled secret protection and committed a sensitive file to the repository. Now, let's review our open secret scanning alerts and close one. 4 | 5 | ### :keyboard: Activity: Triage secret scanning alerts 6 | 7 | 1. In the header of your repository, click the **Security** tab. 8 | 9 | 1. In the left navigation, select the **Secret scanning** option. 10 | 11 | 1. Notice various options in the header bar that can help triage our alerts. 12 | 13 | list of filtered open alerts 14 | 15 | 1. Click the **Provider** dropdown and select `Amazon AWS` to filter the view. Notice only 2 of the 3 entries are listed now. 16 | 17 | list of filtered open alerts 18 | 19 | ### :keyboard: Activity: Review a secret scanning alert 20 | 21 | 1. In the list of open alerts, select the `Amazon AWS Access Key ID` alert. This will open a details page with more information. 22 | 23 | 1. At the top of the page, we can quickly view the alert status, when it was opened, the exposed secret, and some remediation steps. 24 | 25 | image 26 | 27 | 1. Scroll down slightly to the **Detected in X locations** area and you will see all the places where this secret was detected, including the `credentials.yml` file that you created. Notice that secret protection doesn't create duplicate alerts for the same secret found across multiple locations, for example in our learning issue. 28 | 29 | image 30 | 31 | ### :keyboard: Activity: Close an alert 32 | 33 | When secret protection finds a secret in your repository, the first thing you should do is **disable that secret with the provider**. You should assume it has been exposed. 34 | 35 | > [!TIP] 36 | > Some [supported secrets](https://docs.github.com/en/code-security/secret-scanning/introduction/supported-secret-scanning-patterns#default-patterns) are automatically sent to the provider when leaked. 37 | 38 | 1. Assuming you have taken remediation steps, we can update the status of our alert. In the top right, select the **Close as** dropdown. 39 | 40 | > 🚨 **Caution:** Do **NOT** close an open alert without performing remediation steps. This simply hides the problem and provides a false sense of security. It might even trigger additional alerts with your cybersecurity department. 🤦 41 | 42 | 1. Choose the `Revoked` option and enter a useful description of your remediation steps in the comment box (example below). Then choose **Close alert**. 43 | 44 | ```txt 45 | The secret owner was contacted. They provided proof that the exposed secret was replaced. 46 | ``` 47 | 48 | > 💡 **Tip:** This is important so the audit log can later provide critical information if an investigation is required. 49 | 50 | Screenshot of an alert being closed as revoked with a useful comment 51 | 52 | 53 | 1. The alert status now displays `Closed` and the audit trail includes our explanation. 54 | 55 | image 56 | 57 | image 58 | 59 | 1. With at least one of our alerts resolved, let's add a comment to inform Mona we are done with this step, so she can share the next one. 60 | 61 | ```txt 62 | Hello @professortocat, I've resolved the security alert. What's next? 63 | ``` 64 | -------------------------------------------------------------------------------- /.github/steps/3-enable-push-protection.md: -------------------------------------------------------------------------------- 1 | ## Step 3: Enable push protection 2 | 3 | In this section, you will configure your repository to prevent new secrets from being exposed. 4 | 5 | ### What is push protection? 6 | 7 | When someone tries to send code changes to GitHub (a push), secret scanning checks for high-confidence secrets. Secret scanning lists any secrets it detects so the author can review the secrets and remove them or, if needed, allow those secrets to be pushed. 8 | 9 | ### :keyboard: Activity: Configure push protection 10 | 11 | > [!IMPORTANT] 12 | > We disabled push protection in our first step for learning practice. It is normally enabled by default for all public repositories. 13 | 14 | 1. In the header of your repository, click the **Settings** tab. 15 | 1. In the left navigation, under the **Security** section, select **Advanced Security**. 16 | 1. Scroll down past the **Code Scanning** and **Dependabot** sections until you find the **Secret Protection** section. 17 | 1. Adjust the default configuration to match the below. 18 | 19 | - **Secret Protection:** `enabled` 20 | - **Push Protection:** `enabled` 21 | 22 | Secret protection configuration settings 23 | 24 | ### :keyboard: Activity: Attempt to push a secret 25 | 26 | Now that secret push protection is enabled, let's give it a test! 27 | 28 | 1. In the header of your repository, click the **Code** tab. 29 | 30 | 1. In the list of files, click on the `credentials.yml` file to preview it. 31 | 32 | 1. Above the content preview, click the **Edit** button. 33 | 34 | pencil-light 35 | 36 | 1. Copy the following inactive secret to the file, removing the `` text. It should look like the below screenshot. 37 | 38 | ```txt 39 | github-token: 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 40 | ``` 41 | 42 | ![Screenshot of credentials.yml being edited in the GitHub web interface. A newly added github-token is highlighted.](https://github.com/user-attachments/assets/d5e16dc7-ffa9-422a-bc37-89f5cbb26a2e) 43 | 44 | 1. In the top right, use the **Commit changes...** button to **try to** commit directly to the `main` branch. Instead of committing the updated file, a push protection alert appeared. Nice! 🥰 45 | 46 | image 47 | 48 | > [!IMPORTANT] 49 | > Secret Push Protection only scans while _**pushing**_ to GitHub. It cannot check your local commits. If you have a secret in a local commit and it is several commits deep, you will need to remove the secret from your branch's commit history. See [resolving a blocked push on the command line](https://docs.github.com/en/code-security/secret-scanning/pushing-a-branch-blocked-by-push-protection#resolving-a-blocked-push-on-the-command-line). 50 | 51 | ### :keyboard: Activity: Bypass push protection 52 | 53 | In some cases, you may write code that looks similar to a secret and a commit is incorrectly blocked. For example writing tests for an authorization process. In those situations, you can choose to bypass push protection. Let's practice that. 54 | 55 | 1. Select the radio button next to `It's used in tests`. Notice the description, matches our current learning use case. 56 | 57 | image 58 | 59 | 1. Click **Allow secret**. A notification banner reports that you can now try committing again. 60 | 61 | 1. In the top right, use the **Commit changes...** button to commit directly to the `main` branch. 62 | 63 | 1. With the file updated, Mona should be busy checking your work. After checking, she'll provide feedback and the final review. Nice work! You are all done! 🎉 64 | -------------------------------------------------------------------------------- /.github/steps/x-review.md: -------------------------------------------------------------------------------- 1 | ## Review 📖 2 | 3 | _Congratulations friend, you've completed this course!_ 4 | 5 | Here's a recap of all the tasks you've accomplished in your repository: 6 | 7 | - Enabled secret scanning if your repository has private or internal visibility 8 | - Committed a secret to the repository 9 | - Reviewed secrets that have been identified by secret scanning 10 | - Closed a secret scanning alert 11 | - Enabled secret scanning push protection to prevent secrets from being written to the repository (required only for private or internal repositories) 12 | - Attempted to commit a secret, but had that commit stopped by push protection 13 | - Bypassed push protection 14 | 15 | It's important to note that secret scanning capabilities are available for free for all public repositories. Customers who want to enable secret scanning on private repos should find out more about [GitHub Advanced Security](https://docs.github.com/en/enterprise-cloud@latest/get-started/learning-about-github/about-github-advanced-security) or [Set up a trial of GitHub Advanced Security](https://docs.github.com/en/enterprise-cloud@latest/billing/managing-billing-for-github-advanced-security/setting-up-a-trial-of-github-advanced-security). 16 | 17 | In addition to the features you worked with here, GitHub Advanced Security also provides the following features: 18 | 19 | - Custom secret scanning patterns 20 | - Non-partner and generic patterns including passwords, RSA and SSH keys, and database connection strings 21 | - Code scanning with CodeQL 22 | - Security Overview 23 | - Supply chain security capabilities 24 | 25 | ### What's next? 26 | 27 | - [Take another Skills Exercise](https://skills.github.com). 28 | - [Read the GitHub Getting Started docs](https://docs.github.com/en/get-started). 29 | - To find projects to contribute to, check out [GitHub Explore](https://github.com/explore). 30 | -------------------------------------------------------------------------------- /.github/workflows/0-start-exercise.yml: -------------------------------------------------------------------------------- 1 | name: Step 0 # Start Exercise 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | permissions: 9 | contents: write 10 | actions: write 11 | issues: write 12 | 13 | env: 14 | STEP_1_FILE: ".github/steps/1-enable-secret-scanning.md" 15 | 16 | jobs: 17 | start_exercise: 18 | if: | 19 | !github.event.repository.is_template 20 | name: Start Exercise 21 | uses: skills/exercise-toolkit/.github/workflows/start-exercise.yml@v0.3.0 22 | with: 23 | exercise-title: "Introduction to Secret Scanning" 24 | intro-message: "In this exercise, you'll learn how to identify and protect sensitive information in your repositories. 🔍 Let's work together to keep your code secure! 🛡️" 25 | 26 | post_next_step_content: 27 | name: Post next step content 28 | runs-on: ubuntu-latest 29 | needs: [start_exercise] 30 | env: 31 | ISSUE_URL: ${{ needs.start_exercise.outputs.issue-url }} 32 | 33 | steps: 34 | - name: Checkout 35 | uses: actions/checkout@v4 36 | 37 | - name: Get response templates 38 | uses: actions/checkout@v4 39 | with: 40 | repository: skills/response-templates 41 | path: skills-response-templates 42 | 43 | - name: Configure Git user 44 | run: | 45 | git config user.name github-actions[bot] 46 | git config user.email github-actions[bot]@users.noreply.github.com 47 | 48 | - name: Build comment - add step content 49 | id: build-comment 50 | uses: skills/action-text-variables@v2 51 | with: 52 | template-file: ${{ env.STEP_1_FILE }} 53 | template-vars: | 54 | login: ${{ github.actor }} 55 | full_repo_name: ${{ github.repository }} 56 | 57 | - name: Create comment - add step content 58 | run: | 59 | gh issue comment "$ISSUE_URL" \ 60 | --body "$ISSUE_BODY" 61 | env: 62 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 63 | ISSUE_BODY: ${{ steps.build-comment.outputs.updated-text }} 64 | 65 | - name: Create comment - watching for progress 66 | run: | 67 | gh issue comment "$ISSUE_URL" \ 68 | --body-file "skills-response-templates/step-feedback/watching-for-progress.md" 69 | env: 70 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 71 | 72 | - name: Enable next workflow 73 | run: | 74 | gh workflow enable "Step 1" || true 75 | env: 76 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} -------------------------------------------------------------------------------- /.github/workflows/1-enable-secret-scanning.yml: -------------------------------------------------------------------------------- 1 | name: Step 1 # Enable scanning 2 | 3 | on: 4 | push: 5 | paths: 6 | - credentials.yml 7 | 8 | permissions: 9 | contents: read 10 | actions: write 11 | issues: write 12 | 13 | env: 14 | STEP_2_FILE: ".github/steps/2-review-alerts.md" 15 | 16 | jobs: 17 | 18 | find_exercise: 19 | name: Find Exercise Issue 20 | uses: skills/exercise-toolkit/.github/workflows/find-exercise-issue.yml@v0.3.0 21 | 22 | check_step_work: 23 | name: Check Step Work 24 | needs: [find_exercise] 25 | runs-on: ubuntu-latest 26 | env: 27 | ISSUE_URL: ${{ needs.find_exercise.outputs.issue-url }} 28 | 29 | steps: 30 | - name: Checkout 31 | uses: actions/checkout@v4 32 | 33 | - name: Get response templates 34 | uses: actions/checkout@v4 35 | with: 36 | repository: skills/response-templates 37 | path: skills-response-templates 38 | 39 | - name: Update comment - checking work 40 | run: | 41 | gh issue comment "$ISSUE_URL" \ 42 | --body-file skills-response-templates/step-feedback/checking-work.md \ 43 | --edit-last 44 | env: 45 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 46 | 47 | # START: Check practical exercise 48 | 49 | # The fact that the file was updated is enough for now. 50 | # A more detailed check will be added later. 51 | 52 | # END: Check practical exercise 53 | 54 | - name: Create comment - step results 55 | run: | 56 | gh issue comment "$ISSUE_URL" \ 57 | --body "Great job configuring secret protection! 🎉 Now let's take a look at some of the alerts that got created." 58 | env: 59 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 60 | 61 | - name: Build message - step finished 62 | id: build-message-step-finish 63 | uses: skills/action-text-variables@v2 64 | with: 65 | template-file: skills-response-templates/step-feedback/step-finished-prepare-next-step.md 66 | template-vars: | 67 | next_step_number: 2 68 | 69 | - name: Create comment - step finished 70 | run: | 71 | gh issue comment "$ISSUE_URL" \ 72 | --body "$ISSUE_BODY" 73 | env: 74 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 75 | ISSUE_BODY: ${{ steps.build-message-step-finish.outputs.updated-text }} 76 | 77 | post_next_step_content: 78 | name: Post next step content 79 | needs: [find_exercise, check_step_work] 80 | runs-on: ubuntu-latest 81 | env: 82 | ISSUE_URL: ${{ needs.find_exercise.outputs.issue-url }} 83 | 84 | steps: 85 | - name: Checkout 86 | uses: actions/checkout@v4 87 | 88 | - name: Get response templates 89 | uses: actions/checkout@v4 90 | with: 91 | repository: skills/response-templates 92 | path: skills-response-templates 93 | 94 | - name: Create comment - add step content 95 | run: | 96 | gh issue comment "$ISSUE_URL" \ 97 | --body-file "$STEP_2_FILE" 98 | env: 99 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 100 | 101 | - name: Create comment - watching for progress 102 | run: | 103 | gh issue comment "$ISSUE_URL" \ 104 | --body-file skills-response-templates/step-feedback/watching-for-progress.md 105 | env: 106 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 107 | 108 | - name: Enable next workflow 109 | run: | 110 | gh workflow disable "Step 1" || true 111 | gh workflow enable "Step 2" || true 112 | env: 113 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 114 | -------------------------------------------------------------------------------- /.github/workflows/2-review-alerts.yml: -------------------------------------------------------------------------------- 1 | name: Step 2 # Review Alerts 2 | 3 | on: 4 | issue_comment: 5 | types: [created] 6 | 7 | permissions: 8 | contents: write 9 | actions: write 10 | issues: write 11 | 12 | env: 13 | # Keywords required in the issue comment to let this workflow run 14 | REQUIRED_ISSUE_COMMENT_KEYWORDS: "@professortocat" 15 | STEP_3_FILE: ".github/steps/3-enable-push-protection.md" 16 | 17 | jobs: 18 | required_issue_comment_keywords: 19 | name: Check issue comment text for required keywords 20 | runs-on: ubuntu-latest 21 | 22 | steps: 23 | - name: Stop early if missing the expected keywords 24 | run: | 25 | required_keywords=(${REQUIRED_ISSUE_COMMENT_KEYWORDS//,/ }) 26 | for keyword in "${required_keywords[@]}"; do 27 | if [[ ! "$COMMENT_BODY" =~ $keyword ]]; then 28 | echo "Unrecognized request. Ending workflow." 29 | exit 0 30 | fi 31 | done 32 | env: 33 | COMMENT_BODY: ${{ github.event.comment.body }} 34 | 35 | find_exercise: 36 | name: Find Exercise Issue 37 | uses: skills/exercise-toolkit/.github/workflows/find-exercise-issue.yml@v0.3.0 38 | 39 | check_step_work: 40 | name: Check step work 41 | needs: [find_exercise, required_issue_comment_keywords] 42 | runs-on: ubuntu-latest 43 | env: 44 | ISSUE_URL: ${{ needs.find_exercise.outputs.issue-url }} 45 | 46 | steps: 47 | - name: Checkout 48 | uses: actions/checkout@v4 49 | 50 | - name: Get response templates 51 | uses: actions/checkout@v4 52 | with: 53 | repository: skills/response-templates 54 | path: skills-response-templates 55 | 56 | - name: Update comment - checking work 57 | run: | 58 | gh issue comment "$ISSUE_URL" \ 59 | --body-file skills-response-templates/step-feedback/checking-work.md 60 | env: 61 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 62 | 63 | # START: Check practical exercise 64 | 65 | # The workflow GITHUB_TOKEN doesn't allow us to verify if any alerts were closed. 66 | # We will trust the learner to ask to proceed. 67 | 68 | # END: Check practical exercise 69 | 70 | - name: Create comment - step results 71 | run: | 72 | gh issue comment "$ISSUE_URL" \ 73 | --body "Great work reviewing security alerts! 🎉 This is exactly what we wanted! GitHub detected the token pattern and alerted us so we could handle it properly." 74 | env: 75 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 76 | 77 | - name: Build message - step finished 78 | id: build-message-step-finish 79 | uses: skills/action-text-variables@v2 80 | with: 81 | template-file: skills-response-templates/step-feedback/step-finished-prepare-next-step.md 82 | template-vars: | 83 | next_step_number: 3 84 | 85 | - name: Create comment - step finished 86 | run: | 87 | gh issue comment "$ISSUE_URL" \ 88 | --body "$ISSUE_BODY" 89 | env: 90 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 91 | ISSUE_BODY: ${{ steps.build-message-step-finish.outputs.updated-text }} 92 | 93 | post_next_step_content: 94 | name: Post next step content 95 | needs: [find_exercise, check_step_work] 96 | runs-on: ubuntu-latest 97 | env: 98 | ISSUE_URL: ${{ needs.find_exercise.outputs.issue-url }} 99 | 100 | steps: 101 | - name: Checkout 102 | uses: actions/checkout@v4 103 | 104 | - name: Get response templates 105 | uses: actions/checkout@v4 106 | with: 107 | repository: skills/response-templates 108 | path: skills-response-templates 109 | 110 | - name: Create comment - add step content 111 | run: | 112 | gh issue comment "$ISSUE_URL" \ 113 | --body-file "$STEP_3_FILE" 114 | env: 115 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 116 | 117 | - name: Create comment - watching for progress 118 | run: | 119 | gh issue comment "$ISSUE_URL" \ 120 | --body-file skills-response-templates/step-feedback/watching-for-progress.md 121 | env: 122 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 123 | 124 | - name: Enable next workflow 125 | run: | 126 | gh workflow disable "Step 2" || true 127 | gh workflow enable "Step 3" || true 128 | env: 129 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 130 | -------------------------------------------------------------------------------- /.github/workflows/3-enable-push-protection.yml: -------------------------------------------------------------------------------- 1 | name: Step 3 # Enable push protection 2 | 3 | on: 4 | push: 5 | paths: 6 | - credentials.yml 7 | 8 | permissions: 9 | contents: write 10 | actions: write 11 | issues: write 12 | 13 | env: 14 | REVIEW_FILE: ".github/steps/x-review.md" 15 | 16 | jobs: 17 | find_exercise: 18 | name: Find Exercise Issue 19 | uses: skills/exercise-toolkit/.github/workflows/find-exercise-issue.yml@v0.3.0 20 | 21 | check_step_work: 22 | name: Check if push protection is enabled 23 | needs: [find_exercise] 24 | runs-on: ubuntu-latest 25 | env: 26 | ISSUE_URL: ${{ needs.find_exercise.outputs.issue-url }} 27 | 28 | steps: 29 | - name: Checkout 30 | uses: actions/checkout@v4 31 | 32 | - name: Get response templates 33 | uses: actions/checkout@v4 34 | with: 35 | repository: skills/response-templates 36 | path: skills-response-templates 37 | 38 | - name: Update comment - checking work 39 | run: | 40 | gh issue comment "$ISSUE_URL" \ 41 | --body-file skills-response-templates/step-feedback/checking-work.md \ 42 | --edit-last 43 | env: 44 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 45 | 46 | # START: Check practical exercise 47 | 48 | # The fact that the file was updated is enough for now. 49 | # A more detailed check will be added later. 50 | 51 | # END: Check practical exercise 52 | 53 | - name: Create comment - step results 54 | run: | 55 | gh issue comment "$ISSUE_URL" \ 56 | --body "Excellent! 🛡️ Push protection is now enabled. Your repository is ready to block any accidental commits containing secrets." 57 | env: 58 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 59 | 60 | - name: Create comment - step finished - final review next 61 | run: | 62 | gh issue comment "$ISSUE_URL" \ 63 | --body-file skills-response-templates/step-feedback/lesson-review.md 64 | env: 65 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 66 | 67 | post_review_content: 68 | name: Post review content 69 | needs: [find_exercise, check_step_work] 70 | runs-on: ubuntu-latest 71 | env: 72 | ISSUE_URL: ${{ needs.find_exercise.outputs.issue-url }} 73 | 74 | steps: 75 | - name: Checkout 76 | uses: actions/checkout@v4 77 | 78 | - name: Create comment - add step content 79 | run: | 80 | gh issue comment "$ISSUE_URL" \ 81 | --body-file "$REVIEW_FILE" 82 | env: 83 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 84 | 85 | - name: Enable next workflow 86 | run: | 87 | gh workflow disable "Step 3" || true 88 | env: 89 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 90 | 91 | finish_exercise: 92 | name: Finish Exercise 93 | needs: [find_exercise, post_review_content] 94 | uses: skills/exercise-toolkit/.github/workflows/finish-exercise.yml@v0.3.0 95 | with: 96 | issue-url: ${{ needs.find_exercise.outputs.issue-url }} 97 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled source # 2 | ################### 3 | *.com 4 | *.class 5 | *.dll 6 | *.exe 7 | *.o 8 | *.so 9 | 10 | # Packages # 11 | ############ 12 | # it's better to unpack these files and commit the raw source 13 | # git has its own built in compression methods 14 | *.7z 15 | *.dmg 16 | *.gz 17 | *.iso 18 | *.jar 19 | *.rar 20 | *.tar 21 | *.zip 22 | 23 | # Logs and databases # 24 | ###################### 25 | *.log 26 | *.sql 27 | *.sqlite 28 | 29 | # OS generated files # 30 | ###################### 31 | .DS_Store 32 | .DS_Store? 33 | ._* 34 | .Spotlight-V100 35 | .Trashes 36 | ehthumbs.db 37 | Thumbs.db 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) GitHub, Inc. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Introduction to secret protection 2 | 3 | _Learn how to configure secret protection to identify secrets and prevent new ones from being committed to your repository._ 4 | 5 | ## Welcome 6 | 7 | Plain-text credentials accidentally stored in repositories on GitHub are a common target for attackers. In fact, we find well over a million tokens stored on the GitHub platform each year. Let's learn how to prevent that! 8 | 9 | - **Who is this for**: Developers, DevOps Engineers, security teams. 10 | - **What you'll learn**: How to identify plain-text credentials in your repository and how to prevent them from being exposed on GitHub in future pushes. 11 | - **Prerequisites**: Basics of git and GitHub functionality. We recommend you complete [Introduction to GitHub](https://github.com/skills/introduction-to-github). 12 | - **How long**: This course takes less than 15 minutes to complete. 13 | 14 | In this course, you will: 15 | 16 | 1. Enable secret protection 17 | 2. Identify secrets stored in your repository 18 | 3. Enable push protection 19 | 4. Stop secrets from being written to your repository 20 | 21 | ### How to start this exercise 22 | 23 | Simply copy the exercise to your account, then give your favorite Octocat (Mona) **about 20 seconds** to prepare the first lesson, then **refresh the page**. 24 | 25 | [![start-exercise](https://img.shields.io/badge/Copy%20Exercise-%E2%86%92-1f883d?style=for-the-badge&logo=github&labelColor=197935)](https://github.com/new?template_owner=skills&template_name=introduction-to-secret-scanning&owner=%40me&name=skills-introduction-to-secret-scanning&description=GitHub+Skills:+Introduction+to+Secret+Scanning&visibility=public) 26 | 27 |
28 | Having trouble? 🤷
29 | 30 | When copying the exercise, we recommend the following settings: 31 | 32 | - For owner, choose your personal account or an organization to host the repository. 33 | 34 | - We recommend creating a public repository, since private repositories will use Actions minutes. 35 | 36 | If the exercise isn't ready in 20 seconds, please check the [Actions](../../actions) tab. 37 | 38 | - Check to see if a job is running. Sometimes it simply takes a bit longer. 39 | 40 | - If the page shows a failed job, please submit an issue. Nice, you found a bug! 🐛 41 | 42 |
43 | 44 | --- 45 | 46 | © 2025 GitHub • [Code of Conduct](https://www.contributor-covenant.org/version/2/1/code_of_conduct/code_of_conduct.md) • [MIT License](https://gh.io/mit) --------------------------------------------------------------------------------