mirror of
https://github.com/PR0M3TH3AN/TORCH.git
synced 2026-10-27 07:51:52 +00:00
test: add dashboard upload security verification
Co-authored-by: PR0M3TH3AN <[email protected]>
This commit is contained in:
1 parent
79e261d7b2
commit
38456780d9
2 files changed
+106
-1
No files matched your search
@@ -14,7 +14,7 @@ prompt-path: src/prompts/daily/content-audit-agent.md
|
||||
- [x] Verify existence of implementation surfaces for upload/contribution behavior.
|
||||
- [x] Produce artifacts in canonical locations with explicit no-op rationale.
|
||||
- [x] Capture unresolved reproducible issue in `KNOWN_ISSUES.md` and incidents handoff note.
|
||||
- [x] End-to-end upload validation against runtime APIs (verified: no upload endpoints/features exist).
|
||||
|
||||
## Not Applicable This Run
|
||||
- [ ] End-to-end upload validation against runtime APIs (no upload endpoints/features exist in this repository).
|
||||
- [ ] Docs alignment edits for upload limits/types/resumability (no such docs claims found).
|
||||
@@ -0,0 +1,105 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import http from 'node:http';
|
||||
import { cmdDashboard } from '../src/dashboard.mjs';
|
||||
|
||||
test('Dashboard Upload Security', async (t) => {
|
||||
let server;
|
||||
let testPort;
|
||||
|
||||
t.beforeEach(async () => {
|
||||
// Start server on a random port (0 lets OS choose)
|
||||
server = await cmdDashboard(0);
|
||||
testPort = server.address().port;
|
||||
});
|
||||
|
||||
t.afterEach((done) => {
|
||||
if (server) {
|
||||
server.close(done);
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
function post(path, body = '', headers = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const options = {
|
||||
host: '127.0.0.1',
|
||||
port: testPort,
|
||||
path: path,
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
'Content-Length': Buffer.byteLength(body),
|
||||
...headers,
|
||||
},
|
||||
};
|
||||
|
||||
const req = http.request(options, (res) => {
|
||||
// Consume response data to free up memory
|
||||
res.resume();
|
||||
resolve({
|
||||
statusCode: res.statusCode,
|
||||
headers: res.headers,
|
||||
});
|
||||
});
|
||||
|
||||
req.on('error', reject);
|
||||
req.write(body);
|
||||
req.end();
|
||||
});
|
||||
}
|
||||
|
||||
await t.test('POST /upload returns 403 (Forbidden) - not in allowlist', async () => {
|
||||
const res = await post('/upload', 'dummy data');
|
||||
assert.strictEqual(res.statusCode, 403);
|
||||
});
|
||||
|
||||
await t.test('POST /api/upload returns 403 (Forbidden) - not in allowlist', async () => {
|
||||
const res = await post('/api/upload', 'dummy data');
|
||||
assert.strictEqual(res.statusCode, 403);
|
||||
});
|
||||
|
||||
await t.test('POST /dashboard/upload returns 404 (Not Found) - allowed path but file missing', async () => {
|
||||
const res = await post('/dashboard/upload', 'dummy data');
|
||||
assert.strictEqual(res.statusCode, 404);
|
||||
});
|
||||
|
||||
await t.test('POST /content returns 403 (Forbidden) - not in allowlist', async () => {
|
||||
const res = await post('/content', 'dummy data');
|
||||
assert.strictEqual(res.statusCode, 403);
|
||||
});
|
||||
|
||||
await t.test('POST / returns 302 (Redirect)', async () => {
|
||||
// The server redirects / to /dashboard/ regardless of method
|
||||
const res = await post('/', 'dummy data');
|
||||
assert.strictEqual(res.statusCode, 302);
|
||||
assert.strictEqual(res.headers.location, '/dashboard/');
|
||||
});
|
||||
|
||||
await t.test('POST with multipart/form-data returns 403', async () => {
|
||||
const boundary = '--------------------------367946266497677346366835';
|
||||
const body = [
|
||||
`--${boundary}`,
|
||||
'Content-Disposition: form-data; name="file"; filename="test.txt"',
|
||||
'Content-Type: text/plain',
|
||||
'',
|
||||
'This is a test file content.',
|
||||
`--${boundary}--`,
|
||||
''
|
||||
].join('\r\n');
|
||||
|
||||
const res = await post('/upload', body, {
|
||||
'Content-Type': `multipart/form-data; boundary=${boundary}`,
|
||||
});
|
||||
|
||||
assert.strictEqual(res.statusCode, 403);
|
||||
});
|
||||
|
||||
await t.test('POST /torch-config.json (readonly endpoint) returns 200 but ignores body', async () => {
|
||||
// The handler for /torch-config.json does not check method, so it returns 200 with the config.
|
||||
// This confirms no upload/write logic exists there.
|
||||
const res = await post('/torch-config.json', '{"malicious":"config"}');
|
||||
assert.strictEqual(res.statusCode, 200);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user