Overview
Incoming route parameters and query strings are currently passed directly to the oracle and cache layers without validation. Invalid inputs cause uncaught errors or unexpected behaviour rather than clear 400 responses.
Problems Found
GET /api/v1/prices/:assetCode — no validation on assetCode (could be empty string, 200-char garbage, or SQL/XSS payload)
?issuer= query param not validated as a valid Stellar G-address
- Future POST bodies for webhooks/airdrops need schema validation
Solution
Add Zod for schema validation with a thin Express middleware wrapper:
Schemas to define
// src/validation/schemas.js
const assetCodeSchema = z.string().min(1).max(12).regex(/^[A-Z0-9]+$/);
const issuerSchema = z.string().regex(/^G[A-Z2-7]{55}$/).optional();
const paginationSchema = z.object({
page: z.coerce.number().int().min(1).default(1),
limit: z.coerce.number().int().min(1).max(100).default(20),
});
Validation middleware
// src/middleware/validate.js
function validate(schema, source = 'body') {
return (req, res, next) => {
const result = schema.safeParse(req[source]);
if (!result.success) {
return res.status(400).json({
error: 'Validation failed',
details: result.error.flatten().fieldErrors,
});
}
req.validated = result.data;
next();
};
}
Acceptance Criteria
Overview
Incoming route parameters and query strings are currently passed directly to the oracle and cache layers without validation. Invalid inputs cause uncaught errors or unexpected behaviour rather than clear 400 responses.
Problems Found
GET /api/v1/prices/:assetCode— no validation onassetCode(could be empty string, 200-char garbage, or SQL/XSS payload)?issuer=query param not validated as a valid Stellar G-addressSolution
Add Zod for schema validation with a thin Express middleware wrapper:
Schemas to define
Validation middleware
Acceptance Criteria
validatemiddleware created and exportedassetCodevalidated: 1–12 uppercase alphanumeric charsissuervalidated as valid Stellar public key format when present{ error, details }