Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
{
"name": "OWASP WrongSecrets (Java 26 & Node.js 26 Dev Container)",
"image": "eclipse-temurin:26-jdk-jammy",
"features": {
"ghcr.io/devcontainers/features/node:1": {
"version": "26"
},
"ghcr.io/devcontainers/features/python:1": {
"version": "3.12"
},
"ghcr.io/devcontainers/features/terraform:1": {
"version": "latest",
"tflint": "latest"
},
"ghcr.io/devcontainers-contrib/features/terraform-docs:1": {},
"ghcr.io/devcontainers/features/docker-in-docker:2": {
"enableOnStartup": true
},
"ghcr.io/devcontainers/features/git:1": {},
"ghcr.io/devcontainers/features/common-utils:2": {
"installZsh": true,
"configureZshAsDefaultShell": true
}
},
"containerEnv": {
"DEVCONTAINER_SECRET": "WSECR-devcontainer-token-774921"
},
"forwardPorts": [8080, 8090],
"portsAttributes": {
"8080": {
"label": "WrongSecrets Web UI",
"onAutoForward": "notify"
},
"8090": {
"label": "WrongSecrets Vault UI",
"onAutoForward": "silent"
}
},
"customizations": {
"vscode": {
"extensions": [
"vscjava.vscode-java-pack",
"ms-azuretools.vscode-docker",
"redhat.vscode-yaml",
"redhat.vscode-xml",
"eamodio.gitlens",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"asciidoctor.asciidoctor-vscode",
"hashicorp.terraform"
],
"settings": {
"java.configuration.runtimes": [
{
"name": "JavaSE-26",
"path": "/opt/java/openjdk",
"default": true
}
],
"java.compile.nullAnalysis.mode": "automatic"
}
}
},
"postCreateCommand": "chmod +x ./mvnw && ./mvnw dependency:resolve -DskipTests && npm install && pip install pre-commit && pre-commit install && pre-commit install --hook-type commit-msg",
"remoteUser": "root"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @sandeshkuldharme1 ! I think we are missing a few components voor a devcontainer yet. Can you add those please?

}
5 changes: 2 additions & 3 deletions .github/workflows/github-pages-preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,15 @@ permissions:
pages: write
id-token: write
pull-requests: write

# Allow only one concurrent deployment per PR, but allow multiple PRs to deploy simultaneously
# Allow only one concurrent deployment per PR, but allow multiple PRs to deploy
concurrency:
group: "pages-pr-${{ github.event.number }}"
cancel-in-progress: true

env:
NVD_API_KEY: ${{ secrets.NVD_API_KEY }}


jobs:
generate-static-preview:
runs-on: ubuntu-latest
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pr-preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ jobs:
uses: docker/build-push-action@v6
with:
context: .
push: true
push: false

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah no, please keep this true, i understand it will fail for first time contributors and on forks, but that is fine :) we use it all the time for new feature testing

Suggested change
push: false
push: true

platforms: linux/amd64,linux/arm64
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
Expand Down
34 changes: 34 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,40 @@ Pull requests should be as small/atomic as possible. Large, wide-sweeping change

## How to set up your Contributor Environment

### Using Dev Containers (Zero Local Dependencies)

The project includes a fully configured Dev Container for **VS Code** and **GitHub Codespaces**. You do not need to install Java, Maven, Node.js, Python, or Terraform tools locally on your machine—everything is self-contained inside the Dev Container.

The Dev Container environment automatically provides:
- **JDK 26** & **Maven Wrapper** (`./mvnw`)
- **Node.js 26** & **npm** (for commitlint, ESLint, and frontend build)
- **Python 3** & **pre-commit** hooks
- **Terraform**, **tflint**, and **terraform-docs** (for pre-commit validation)
- **Docker-in-Docker** (for running Docker-based challenge environments)
- Pre-configured VS Code extensions and settings

#### 1. Open in Dev Container
- **In VS Code**: Press `Ctrl+Shift+P` (or `Cmd+Shift+P` on macOS) -> select **"Dev Containers: Reopen in Container"** (or click the prompt in the bottom-left corner).
- **In GitHub Codespaces**: Select **Code** -> **Codespaces** -> **Create codespace on this branch**.

*(The container automatically installs all dependencies, configures pre-commit hooks, and runs dependency resolution on launch).*

#### 2. Build and Test the Application
Inside the Dev Container integrated terminal, run:

```bash
# Compile and run tests
./mvnw clean compile test

# Start the application
./mvnw spring-boot:run

# Run pre-commit checks across all files
pre-commit run --all-files
```

### Manual Setup

1. Create a GitHub account. Multiple different GitHub subscription plans are available, but you only need a free one. Follow [these steps](https://help.github.com/en/articles/signing-up-for-a-new-github-account "Signing up for a new GitHub account") to set up your account.
2. Fork the repository. Creating a fork means creating a copy of the repository on your own account, which you can modify without any impact on this repository. GitHub has an [article that describes all the needed steps](https://help.github.com/en/articles/fork-a-repo "Fork a repo").
3. Clone your own repository to your host computer so that you can make modifications. If you followed the GitHub tutorial from step 2, you have already done this.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package org.owasp.wrongsecrets.challenges.docker;

import org.owasp.wrongsecrets.challenges.FixedAnswerChallenge;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/** Challenge for finding secrets leaked in Dev Container configurations and environments. */
@Component
public class Challenge67 extends FixedAnswerChallenge {

private final String devcontainerSecret;

/**
* Constructor for creating a new Challenge67 object.
*
* @param devcontainerSecret The secret configured in the Dev Container environment.
*/
public Challenge67(
@Value("${DEVCONTAINER_SECRET:WSECR-devcontainer-token-774921}") String devcontainerSecret) {
this.devcontainerSecret = devcontainerSecret;
}

@Override
public String getAnswer() {
return this.devcontainerSecret;
}
}
20 changes: 20 additions & 0 deletions src/main/resources/challenges/challenge-67/challenge-67.snippet
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<div id="devcontainer-challenge-container" style="border: 1px solid #ccc; border-radius: 8px; padding: 20px; margin: 20px; background-color: #f9f9f9;">
<h4>🐳 Dev Container Configuration Inspector</h4>
<p>Development containers allow teams to share reproducible development environments. However, committing hardcoded environment variables or secrets into <code>.devcontainer/devcontainer.json</code> can expose sensitive credentials to anyone with repository access.</p>

<div style="background-color: #1e1e1e; color: #d4d4d4; padding: 15px; border-radius: 6px; font-family: monospace; font-size: 13px; overflow-x: auto; margin-top: 15px;">
<span style="color: #6a9955;">// .devcontainer/devcontainer.json excerpt</span><br>
{<br>
&nbsp;&nbsp;<span style="color: #9cdcfe;">"name"</span>: <span style="color: #ce9178;">"OWASP WrongSecrets (Java 26 &amp; Node.js 26 Dev Container)"</span>,<br>
&nbsp;&nbsp;<span style="color: #9cdcfe;">"image"</span>: <span style="color: #ce9178;">"eclipse-temurin:26-jdk-jammy"</span>,<br>
&nbsp;&nbsp;<span style="color: #9cdcfe;">"containerEnv"</span>: {<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #9cdcfe;">"DEVCONTAINER_SECRET"</span>: <span style="color: #ce9178;">"WSECR-devcontainer-token-774921"</span><br>
&nbsp;&nbsp;},<br>
&nbsp;&nbsp;<span style="color: #9cdcfe;">"postCreateCommand"</span>: <span style="color: #ce9178;">"chmod +x ./mvnw &amp;&amp; ./mvnw dependency:resolve -DskipTests &amp;&amp; npm install &amp;&amp; pip install pre-commit &amp;&amp; pre-commit install"</span><br>
}
</div>

<div class="devcontainer-tip" style="margin-top: 15px; font-size: 12px; color: #666;">
💡 Tip: Check the <code>DEVCONTAINER_SECRET</code> environment variable defined in the Dev Container configuration.
</div>
</div>
11 changes: 11 additions & 0 deletions src/main/resources/explanations/challenge67.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
=== Dev Container Secret Leak

Development containers (Dev Containers) allow teams to define reproducible development environments using containerization tools like VS Code Remote - Containers and GitHub Codespaces. By encapsulating tools, runtimes, and dependencies within `.devcontainer/devcontainer.json`, developers can get started without installing complex local software stacks.

However, developers frequently make the mistake of embedding sensitive tokens, passwords, API keys, or private registry access credentials directly into `.devcontainer/devcontainer.json` (such as in `containerEnv`, `remoteEnv`, or lifecycle scripts) and committing them to version control.

To solve this challenge:

. Inspect the `.devcontainer/devcontainer.json` configuration file in the project repository or review the configuration snippet in the UI.
. Identify the leaked `DEVCONTAINER_SECRET` or token defined in the container environment.
. Submit the discovered secret in the input field below.
10 changes: 10 additions & 0 deletions src/main/resources/explanations/challenge67_hint.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
You can solve this challenge using the following steps:

1. Inspect the Dev Container configuration file:
- Open the `.devcontainer/devcontainer.json` file in the root of the repository.
- Look for the `containerEnv` or `remoteEnv` sections where environment variables are defined.

2. Inspect the running container environment:
- If running inside a dev container or Docker container, check the environment variables with `printenv DEVCONTAINER_SECRET` or `echo $DEVCONTAINER_SECRET`.

3. Review the UI snippet provided on this challenge page for the exposed configuration.
16 changes: 16 additions & 0 deletions src/main/resources/explanations/challenge67_reason.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
= Dev Container Configuration Secret Exposure

*Why Hardcoding Secrets in Dev Containers is a Critical Security Risk*

Dev Containers are shared development environments configured via `.devcontainer/devcontainer.json`. Because these files are typically tracked in version control, hardcoding secrets into devcontainer definitions presents several security dangers:

1. **Exposure to All Repository Readers**: Anyone with read access to the source repository (or public forks and clones in open-source projects) can read secrets hardcoded in `.devcontainer/devcontainer.json`.
2. **Environment Variable Leakage**: Credentials defined in `containerEnv` or `remoteEnv` are injected into every process inside the container, making them accessible to any script, child process, or diagnostic tool running in the container.
3. **Persistent in Git History**: Once committed, removing the secret requires git history rewrites, and stale keys often remain valid indefinitely if rotation is not performed.

*Remediation and Best Practices:*

- **Use GitHub Codespaces Secrets / VS Code Dev Container Secrets**: Inject secrets dynamically via Codespaces repository/user secrets or VS Code settings rather than hardcoding them in configuration files.
- **Use Local Environment Substitution**: Reference host environment variables dynamically in `devcontainer.json` using `${localEnv:MY_SECRET}` syntax.
- **Use `.env` files with `.gitignore`**: Place development secrets in local `.env` files that are explicitly excluded from version control in `.gitignore`.
- **Adopt Secret Management Solutions**: Fetch secrets at runtime using dedicated secret managers (e.g., HashiCorp Vault, AWS Secrets Manager, Azure Key Vault, GCP Secret Manager).
15 changes: 15 additions & 0 deletions src/main/resources/wrong-secrets-configuration.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1014,6 +1014,20 @@ configurations:
ctf:
enabled: true

- name: Challenge 67
short-name: "challenge-67"
sources:
- class-name: "org.owasp.wrongsecrets.challenges.docker.Challenge67"
explanation: "explanations/challenge67.adoc"
hint: "explanations/challenge67_hint.adoc"
reason: "explanations/challenge67_reason.adoc"
ui-snippet: "challenges/challenge-67/challenge-67.snippet"
environments: *all_envs
difficulty: *easy
category: *docker_tech
ctf:
enabled: true

- name: Challenge 68
short-name: "challenge-68"
sources:
Expand All @@ -1040,6 +1054,7 @@ configurations:
category: *ai
ctf:
enabled: true

- name: Challenge 70
short-name: "challenge-70"
sources:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package org.owasp.wrongsecrets.challenges.docker;

import static org.assertj.core.api.Assertions.assertThat;

import org.junit.jupiter.api.Test;
import org.owasp.wrongsecrets.challenges.Spoiler;

class Challenge67Test {

private static final String DEFAULT_SECRET = "WSECR-devcontainer-token-774921";

@Test
void spoilerShouldRevealAnswer() {
var challenge = new Challenge67(DEFAULT_SECRET);

assertThat(challenge.spoiler()).isEqualTo(new Spoiler(DEFAULT_SECRET));
}

@Test
void rightAnswerShouldSolveChallenge() {
var challenge = new Challenge67(DEFAULT_SECRET);

assertThat(challenge.answerCorrect(DEFAULT_SECRET)).isTrue();
}

@Test
void incorrectAnswerShouldNotSolveChallenge() {
var challenge = new Challenge67(DEFAULT_SECRET);

assertThat(challenge.answerCorrect("wrong-secret-token")).isFalse();
}
}
Loading