fix(security): move hardcoded HMAC secret to environment variable

The benchmark submission HMAC signing secret was hardcoded in source
code (CWE-798), allowing anyone reading the open-source repository to
extract it and forge benchmark submissions to benchmark.projectnomad.us.

- Read BENCHMARK_HMAC_SECRET from env instead of embedding it in code
- Register the variable in the AdonisJS env schema (optional)
- Add a guard in submitToRepository() that rejects submissions when
  the secret is not configured
- Document the new variable in .env.example

The benchmark server operator must now inject the real secret via the
BENCHMARK_HMAC_SECRET environment variable (e.g. in docker-compose or
a .env file).  The previously committed secret should be rotated
server-side.
This commit is contained in:
Sebastion 2026-03-25 08:00:43 +00:00
parent efe6af9b24
commit bc06965ec3
No known key found for this signature in database
3 changed files with 22 additions and 6 deletions

View File

@ -16,3 +16,6 @@ REDIS_PORT=6379
# On Windows dev, use an absolute path like: C:/nomad-storage
# On Linux production, use: /opt/project-nomad/storage
NOMAD_STORAGE_PATH=/opt/project-nomad/storage
# HMAC secret used to sign benchmark submissions to benchmark.projectnomad.us
# Generate with: openssl rand -hex 24
# BENCHMARK_HMAC_SECRET=

View File

@ -23,16 +23,17 @@ import type {
RepositoryStats,
} from '../../types/benchmark.js'
import { randomUUID, createHmac } from 'node:crypto'
import env from '#start/env'
import { DockerService } from './docker_service.js'
import { SERVICE_NAMES } from '../../constants/service_names.js'
import { BROADCAST_CHANNELS } from '../../constants/broadcast.js'
import Dockerode from 'dockerode'
// HMAC secret for signing submissions to the benchmark repository
// This provides basic protection against casual API abuse.
// Note: Since NOMAD is open source, a determined attacker could extract this.
// For stronger protection, see challenge-response authentication.
const BENCHMARK_HMAC_SECRET = '778ba65d0bc0e23119e5ffce4b3716648a7d071f0a47ec3f'
// HMAC secret for signing submissions to the benchmark repository.
// Must be provided via the BENCHMARK_HMAC_SECRET environment variable.
// The benchmark server uses this to verify that submissions originate from
// a genuine NOMAD instance. Never commit the real secret to source control.
const BENCHMARK_HMAC_SECRET = env.get('BENCHMARK_HMAC_SECRET')
// Re-export default weights for use in service
const SCORE_WEIGHTS = {
@ -157,6 +158,11 @@ export class BenchmarkService {
}
try {
// Refuse to submit if the signing secret is not configured
if (!BENCHMARK_HMAC_SECRET) {
throw new Error('Benchmark submission signing secret is not configured. Set the BENCHMARK_HMAC_SECRET environment variable.')
}
// Generate HMAC signature for submission verification
const timestamp = Date.now().toString()
const payload = timestamp + JSON.stringify(submission)

View File

@ -60,4 +60,11 @@ export default await Env.create(new URL('../', import.meta.url), {
|----------------------------------------------------------
*/
NOMAD_API_URL: Env.schema.string.optional(),
/*
|----------------------------------------------------------
| Variables for configuring the benchmark submission secret
|----------------------------------------------------------
*/
BENCHMARK_HMAC_SECRET: Env.schema.string.optional(),
})