Skip to content
Merged
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
14 changes: 7 additions & 7 deletions .github/workflows/dast.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,17 @@ on:
value: ${{ jobs.dast.outputs.result }}

jobs:
# 🚧 REPLACE THIS ENTIRE 'jobs:' SECTION WITH WORKSHOP CONTENT! 🚧
# Copy from: workshop/dast/{tool}/workflow.yml
# 🚧 NOT YET β€” DAST module is planned but not part of v1 of the workshop.
# The workshop/dast/ folder will be added in a future release.
dast:
name: "🚧 DAST - Workshop Placeholder"
name: "🚧 DAST - Coming soon"
runs-on: ubuntu-latest
outputs:
result: ${{ steps.placeholder.outputs.result }}
steps:
- name: Workshop Placeholder
- name: DAST module not yet shipped
id: placeholder
run: |
echo "🚧 Replace this job with content from workshop/dast/{tool}/workflow.yml!"
echo "This will implement: DAST security testing with your chosen tool"
echo "result=workshop-placeholder" >> "$GITHUB_OUTPUT"
echo "🚧 DAST is planned for a future workshop iteration."
echo " For now, this job is a no-op placeholder so the orchestrator stays green."
echo "result=not-yet-shipped" >> "$GITHUB_OUTPUT"
283 changes: 278 additions & 5 deletions code/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions code/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@
"test": "echo 'No tests configured'"
},
"dependencies": {
"lodash": "4.17.15"
"axios": "1.6.0"
},
"devDependencies": {},
"engines": {
"node": ">=18.0.0"
},
"author": "Workshop Team",
"license": "MIT"
}
}
26 changes: 26 additions & 0 deletions code/src/simple-app.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const http = require('http');
const axios = require('axios');

const AWS_ACCESS_KEY_ID = 'AKIA2T2SJH6MS337PDWL'
const AWS_SECRET_ACCESS_KEY = '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'
Expand Down Expand Up @@ -78,6 +79,31 @@ const server = http.createServer((req, res) => {
</body>
</html>
`);
} else if (url === '/fetch' && method === 'POST') {
let body = '';
req.on('data', chunk => { body += chunk; });
req.on('end', async () => {
let targetUrl;
try {
({ url: targetUrl } = JSON.parse(body));
} catch {
res.writeHead(400, { 'Content-Type': 'application/json' });
return res.end(JSON.stringify({ error: 'Invalid JSON' }));
}
if (!targetUrl) {
res.writeHead(400, { 'Content-Type': 'application/json' });
return res.end(JSON.stringify({ error: 'No url provided' }));
}
try {
// TODO: validate URL allow-list before fetching to prevent SSRF
const { status, data } = await axios.get(targetUrl);
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ status, data }));
} catch (err) {
res.writeHead(502, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: err.message }));
}
});
} else if (url === '/data' && method === 'GET') {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
Expand Down
Loading