Skip to content
Closed
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
becb1e0
Initial plan
Copilot Aug 30, 2025
373c7f7
Initial plan
Copilot Aug 30, 2025
a2c07f1
Implement comprehensive devcontainer security hardening
Copilot Aug 30, 2025
64404d9
Add devcontainer port visibility automation and security hardening do…
Copilot Aug 30, 2025
38433d4
Fix bullet point formatting in introduction-to-dev-containers.md
Copilot Aug 30, 2025
921f8d9
Merge pull request #3 from 02ez/copilot/fix-4f8f2aa5-4a54-438f-89e7-b…
02ez Aug 30, 2025
108d1a2
Docs: tighten devcontainer JSON + stable Codespaces port setup
02ez Aug 30, 2025
5b0a086
Use canonical `gh codespace ports visibility`
02ez Aug 30, 2025
a8e8daa
Docs: canonicalize `gh codespace ports visibility` in Python setup
02ez Aug 30, 2025
2fd1fbc
Docs: standardize on `gh codespace ports visibility` and unify examples
02ez Aug 30, 2025
1e1c079
chore(ci): add PR summary using $GITHUB_STEP_SUMMARY
02ez Aug 30, 2025
81b63dc
ci(pr-summary): robust file listing via git diff-tree + precise docs …
02ez Aug 30, 2025
5aff31b
ci(pr-summary): add PR summary via $GITHUB_STEP_SUMMARY (robust diff-…
02ez Aug 30, 2025
f7e8e86
Update pr-summary.yml with new content
02ez Aug 30, 2025
8045d10
Merge pull request #1 from 02ez/copilot/fix-53426d94-92c8-4134-9b70-d…
02ez Aug 30, 2025
2900603
fix: content/actions/reference/workflows-and-actions/dockerfile-suppo…
snyk-bot Sep 1, 2025
57290a5
Merge pull request #10 from 02ez/snyk-fix-dc594754af378df296533088493…
02ez Sep 1, 2025
caad731
fix: Dockerfile.openapi_decorator to reduce vulnerabilities
snyk-bot Sep 1, 2025
4bb0bdb
Merge pull request #11 from 02ez/snyk-fix-dcb79ae3a247dad781581e023a2…
02ez Sep 1, 2025
fafce21
fix: package.json & package-lock.json to reduce vulnerabilities
snyk-bot Sep 1, 2025
863c33b
Merge pull request #12 from 02ez/snyk-fix-ab9a4762951c40794c26c21888e…
02ez Sep 1, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ redirect_from:
- /codespaces/setting-up-your-project-for-codespaces/setting-up-your-project-for-codespaces
children:
- /introduction-to-dev-containers
- /securing-port-forwarding-in-dev-containers
- /setting-up-your-nodejs-project-for-codespaces
- /setting-up-your-dotnet-project-for-codespaces
- /setting-up-your-java-project-for-codespaces
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,17 @@ For information about how to choose your preferred dev container configuration w

{% data reusables.codespaces.more-info-devcontainer %}

#### Security considerations for dev containers

When configuring your dev container, consider security implications, especially for port forwarding and network access:

* **Port visibility**: By default, forwarded ports are private to you. Consider whether ports need to be accessible to your organization or publicly accessible
* **Automated port configuration**: Use `postAttachCommand` with the {% data variables.product.prodname_cli %} to automatically apply consistent port visibility settings
* **Organization policies**: Work within your organization's port visibility policies if they have restrictions in place
* **Minimal port exposure**: Only forward ports that are necessary for development and testing

For detailed guidance on secure port forwarding configurations, see [AUTOTITLE](/codespaces/setting-up-your-project-for-codespaces/adding-a-dev-container-configuration/securing-port-forwarding-in-dev-containers).

#### How to use the devcontainer.json

It's useful to think of the `devcontainer.json` file as providing "customization" rather than "personalization." You should only include things that everyone working on your codebase needs as standard elements of the development environment, not things that are personal preferences. Things like linters are good to standardize on, and to require everyone to have installed, so they're good to include in your `devcontainer.json` file. Things like user interface decorators or themes are personal choices that should not be put in the `devcontainer.json` file.
Expand Down Expand Up @@ -230,4 +241,5 @@ Changes to a configuration will be applied the next time you create a codespace.

## Further reading

* [AUTOTITLE](/codespaces/setting-up-your-project-for-codespaces/adding-a-dev-container-configuration/securing-port-forwarding-in-dev-containers)
* [AUTOTITLE](/codespaces/prebuilding-your-codespaces)
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
---
title: Securing port forwarding in dev containers
shortTitle: Secure port forwarding
intro: 'Learn how to configure secure port forwarding settings in your dev container configuration to control port visibility and automate security settings.'
permissions: People with write permissions to a repository can create or edit the codespace configuration.
versions:
fpt: '*'
ghec: '*'
type: how_to
topics:
- Codespaces
- Set up
- Security
---

## About port forwarding security in dev containers

When you configure a dev container for {% data variables.product.prodname_github_codespaces %}, you can control how ports are forwarded and their visibility settings. This is important for security, especially when working with sensitive applications or in organizations with strict access policies.

By default, {% data variables.product.prodname_github_codespaces %} forwards ports privately, meaning only you can access them. However, you can configure your dev container to automatically apply specific visibility settings when the codespace starts.

## Configuring port forwarding with security in mind

You can configure port forwarding in your dev container using several properties, each serving different security purposes. The key properties for secure port forwarding are `forwardPorts`, `portsAttributes`, and `postAttachCommand`.

### Using forwardPorts with portsAttributes

The most basic approach is to specify which ports should be forwarded and configure their attributes:

```jsonc
{
"name": "My Secure Dev Container",
"image": "mcr.microsoft.com/devcontainers/base:bullseye",

"forwardPorts": [3000, 8080, 8443],

"portsAttributes": {
"3000": {
"label": "Application Server",
"protocol": "http"
},
"8080": {
"label": "API Server",
"protocol": "http"
},
"8443": {
"label": "Secure API",
"protocol": "https"
}
}
}
```

{% data reusables.codespaces.portsattributes-configuration %}

### Automating port visibility settings

You can automate port visibility settings using the `postAttachCommand` property. This ensures consistent security settings every time someone connects to the codespace:

```jsonc
{
"name": "My Secure Dev Container",
"image": "mcr.microsoft.com/devcontainers/base:bullseye",

"forwardPorts": [3000, 8080],

"portsAttributes": {
"3000": {
"label": "Dev Server (Private)"
},
"8080": {
"label": "API Server (Team Only)"
}
},

"features": {
"ghcr.io/devcontainers/features/github-cli:1": {}
},

"postAttachCommand": "gh codespace ports visibility 3000:private 8080:org -c \"$CODESPACE_NAME\""
}
```

{% data reusables.codespaces.port-visibility-automation %}

## Security best practices

{% data reusables.codespaces.port-security-best-practices %}

## Working with organization policies

Organization administrators can set policies that restrict which port visibility options are available. For more information, see [AUTOTITLE](/codespaces/managing-codespaces-for-your-organization/restricting-the-visibility-of-forwarded-ports).

If your organization has port visibility restrictions in place, make sure your dev container automation commands comply with these policies. For example, if your organization disallows public port forwarding, don't use `public` in your `postAttachCommand`.

## Example configurations

The following examples demonstrate different security approaches for common development scenarios.

### Development environment with private ports

```jsonc
{
"name": "Private Development Environment",
"image": "mcr.microsoft.com/devcontainers/javascript-node:0-18",

"forwardPorts": [3000, 3001],

"portsAttributes": {
"3000": {
"label": "Web Server (Private)",
"protocol": "http"
},
"3001": {
"label": "API Server (Private)",
"protocol": "http"
}
},

"features": {
"ghcr.io/devcontainers/features/github-cli:1": {}
},

"postAttachCommand": "gh cs ports visibility 3000:private 3001:private -c \"$CODESPACE_NAME\""
Copy link
Preview

Copilot AI Aug 30, 2025

Choose a reason for hiding this comment

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

The GitHub CLI command syntax should be 'gh codespace ports' instead of 'gh cs ports'.

Copilot uses AI. Check for mistakes.

}
```

### Team collaboration with organization-only ports

```jsonc
{
"name": "Team Collaboration Environment",
"image": "mcr.microsoft.com/devcontainers/python:3-bullseye",

"forwardPorts": [5000, 8000],

"portsAttributes": {
"5000": {
"label": "Flask App (Team)",
"protocol": "http"
},
"8000": {
"label": "Django Admin (Team)",
"protocol": "https"
}
},

"features": {
"ghcr.io/devcontainers/features/github-cli:1": {}
},

"postAttachCommand": "gh codespace ports visibility 5000:org 8000:org -c \"$CODESPACE_NAME\""
}
```

## Further reading

* [AUTOTITLE](/codespaces/developing-in-a-codespace/forwarding-ports-in-your-codespace)
* [AUTOTITLE](/codespaces/managing-codespaces-for-your-organization/restricting-the-visibility-of-forwarded-ports)
* {% data reusables.codespaces.more-info-devcontainer %}
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,82 @@ With your dev container configuration added and a basic understanding of what ev

After the dev container is rebuilt, and your codespace becomes available again, the `postCreateCommand` will have been run, installing npm, and the "Code Spell Checker" extension will be available for use.

## Step 4: Run your application
## Step 4: Configure port forwarding and security

In the previous section, you used the `postCreateCommand` to install a set of packages via the `npm install` command. With the dependencies now installed, you can run the application.
Node.js applications typically run on port 3000. You can configure your dev container to automatically forward this port and set appropriate security settings.

1. Add port forwarding configuration by uncommenting and modifying the `forwardPorts` property:

```jsonc copy
// Use 'forwardPorts' to make a list of ports inside the container available locally.
"forwardPorts": [3000],
```

1. Add port attributes to label your forwarded port:

```jsonc copy
"portsAttributes": {
"3000": {
"label": "Node.js App"
}
},
```

1. For enhanced security, you can add a `postAttachCommand` to automatically set port visibility. Add the {% data variables.product.prodname_cli %} feature first:

```jsonc copy
"features": {
"ghcr.io/devcontainers-contrib/features/jshint:2": {},
"ghcr.io/devcontainers/features/github-cli:1": {}
},
```

1. Then add the `postAttachCommand` to control port visibility:

```jsonc copy
// Automatically set port visibility when attaching to the codespace
"postAttachCommand": "gh cs ports visibility 3000:private -c \"$CODESPACE_NAME\""
Copy link
Preview

Copilot AI Aug 30, 2025

Choose a reason for hiding this comment

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

The GitHub CLI command syntax should be 'gh codespace ports' instead of 'gh cs ports'.

Copilot uses AI. Check for mistakes.

```

Your updated `devcontainer.json` should look similar to this:

```jsonc
{
"name": "Node.js",
"image": "mcr.microsoft.com/devcontainers/javascript-node:0-18-bullseye",
"features": {
"ghcr.io/devcontainers-contrib/features/jshint:2": {},
"ghcr.io/devcontainers/features/github-cli:1": {}
},

"forwardPorts": [3000],

"portsAttributes": {
"3000": {
"label": "Node.js App"
}
},

"postCreateCommand": "npm install",

"postAttachCommand": "gh cs ports visibility 3000:private -c \"$CODESPACE_NAME\"",
Copy link
Preview

Copilot AI Aug 30, 2025

Choose a reason for hiding this comment

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

Same GitHub CLI syntax correction needed - use 'gh codespace ports' instead of 'gh cs ports'.

Copilot uses AI. Check for mistakes.


"customizations": {
"vscode": {
"extensions": [
"streetsidesoftware.code-spell-checker"
]
}
}
}
```

{% data reusables.codespaces.save-changes %}
{% data reusables.codespaces.rebuild-command %}

## Step 5: Run your application

In the previous section, you configured port forwarding for your Node.js application. Now you can run the application and see it in action.

1. In the Terminal of your codespace, enter `npm start`.

Expand All @@ -159,12 +232,14 @@ In the previous section, you used the `postCreateCommand` to install a set of pa

![Screenshot of the port forwarding message, reading "Your application running on port 3000 is available." The "Open in Browser" button is also shown.](/assets/images/help/codespaces/codespaces-port3000-toast.png)

## Step 5: Commit your changes
## Step 6: Commit your changes

{% data reusables.codespaces.committing-link-to-procedure %}

## Next steps

You should now be able to add a custom dev container configuration to your own Node.js, JavaScript, or TypeScript project.

For more advanced port security configurations, see [AUTOTITLE](/codespaces/setting-up-your-project-for-codespaces/adding-a-dev-container-configuration/securing-port-forwarding-in-dev-containers).

{% data reusables.codespaces.next-steps-adding-devcontainer %}
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ The default development container, or "dev container," for {% data variables.pro
## Step 3: Modify your devcontainer.json file

With your dev container configuration added and a basic understanding of what everything does, you can now make changes to customize your environment further. In this example, you'll add properties that will:
* Configure port forwarding for the Flask application with security settings.
* Install a package required by the application.
* Install a {% data variables.product.prodname_vscode_shortname %} extension in this codespace.

Expand All @@ -101,13 +102,46 @@ With your dev container configuration added and a basic understanding of what ev
// "features": {},
```

1. Uncomment the `forwardPorts` property and configure it for Flask (port 5000):

```jsonc copy
// Use 'forwardPorts' to make a list of ports inside the container available locally.
"forwardPorts": [5000],
```

1. Add port attributes and security configuration:

```jsonc copy
"portsAttributes": {
"5000": {
"label": "Flask Application"
}
},
```

1. Add the {% data variables.product.prodname_cli %} feature for port visibility automation:

```jsonc copy
"features": {
"ghcr.io/devcontainers-contrib/features/coverage-py:2": {},
"ghcr.io/devcontainers/features/github-cli:1": {}
},
```

1. Uncomment the `postCreateCommand` property.

```jsonc copy
// Use 'postCreateCommand' to run commands after the container is created.
"postCreateCommand": "pip3 install --user -r requirements.txt",
```

1. Add automated port visibility configuration:

```jsonc copy
// Automatically set port visibility when attaching to the codespace
"postAttachCommand": "gh cs ports visibility 5000:private -c \"$CODESPACE_NAME\""
Copy link
Preview

Copilot AI Aug 30, 2025

Choose a reason for hiding this comment

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

The GitHub CLI command should use 'gh codespace ports' instead of 'gh cs ports' for the correct API syntax.

Copilot uses AI. Check for mistakes.

```

{% data reusables.codespaces.add-extension-to-devcontainer %}

```jsonc
Expand All @@ -118,14 +152,24 @@ With your dev container configuration added and a basic understanding of what ev
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
"image": "mcr.microsoft.com/devcontainers/python:0-3.11-bullseye",
"features": {
"ghcr.io/devcontainers-contrib/features/coverage-py:2": {}
"ghcr.io/devcontainers-contrib/features/coverage-py:2": {},
"ghcr.io/devcontainers/features/github-cli:1": {}
},

// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],
"forwardPorts": [5000],

"portsAttributes": {
"5000": {
"label": "Flask Application"
}
},

// Use 'postCreateCommand' to run commands after the container is created.
"postCreateCommand": "pip3 install --user -r requirements.txt",

// Automatically set port visibility when attaching to the codespace
"postAttachCommand": "gh cs ports visibility 5000:private -c \"$CODESPACE_NAME\"",

// Configure tool-specific properties.
"customizations": {
Expand All @@ -147,7 +191,7 @@ With your dev container configuration added and a basic understanding of what ev
{% data reusables.codespaces.rebuild-command %}
{% data reusables.codespaces.rebuild-reason %}

After the dev container is rebuilt, and your codespace becomes available again, the `postCreateCommand` will have been run, installing the package listed in the `requirements.txt` file, and the "Code Spell Checker" extension will be available for use.
After the dev container is rebuilt, and your codespace becomes available again, the `postCreateCommand` will have been run, installing the package listed in the `requirements.txt` file, the `postAttachCommand` will have configured the port visibility settings, and the "Code Spell Checker" extension will be available for use.

## Step 4: Run your application

Expand All @@ -169,4 +213,6 @@ In the previous section, you used the `postCreateCommand` to install a package f

You should now be able to add a custom dev container configuration to your own Python project.

For more advanced port security configurations, see [AUTOTITLE](/codespaces/setting-up-your-project-for-codespaces/adding-a-dev-container-configuration/securing-port-forwarding-in-dev-containers).

{% data reusables.codespaces.next-steps-adding-devcontainer %}
1 change: 1 addition & 0 deletions data/reusables/codespaces/devcontainer-properties-1.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
* **image:** The name of an image in a container registry ([DockerHub](https://hub.docker.com/), [{% data variables.product.prodname_dotcom %} {% data variables.product.prodname_container_registry %}](/packages/learn-github-packages/introduction-to-github-packages), or [Azure Container Registry](https://azure.microsoft.com/services/container-registry/)) that will be used to create the dev container for the codespace.
* **features:** A list of one or more objects, each of which references one of the available dev container features. Features are self-contained, shareable units of installation code and development container configuration. They provide an easy way to add more tooling, runtime, or library features to your development container. You can add features either within {% data variables.product.prodname_vscode_shortname %} or in the `devcontainer.json` editor on {% data variables.product.github %}. For more information, click either the **{% data variables.product.prodname_vscode %}** or **Web browser** tab in [AUTOTITLE](/codespaces/setting-up-your-project-for-codespaces/configuring-dev-containers/adding-features-to-a-devcontainer-file?tool=webui).
* **forwardPorts:** Any ports listed here will be forwarded automatically. For more information, see [AUTOTITLE](/codespaces/developing-in-codespaces/forwarding-ports-in-your-codespace).
* **portsAttributes:** This property maps specified ports to configuration options such as labels and protocols. {% data reusables.codespaces.portsattributes-configuration %}
Loading
Loading