Sanitized snapshot of private source 13a965dd6ea705dd92499f7dbeaa00c25c15247d. Require same-origin evidence for unsafe methods, fail closed on invalid authentication middleware configuration, and bound untrusted request metadata. AI-Assistance: OpenAI Codex assisted implementation, testing, and security review. Signed-off-by: Cole Speelman <crspeelman@gmail.com>
This commit is contained in:
@@ -16,6 +16,11 @@ import (
|
||||
|
||||
const RecordVersion = 1
|
||||
|
||||
const (
|
||||
maxRecordBytes int64 = 1 << 40
|
||||
maxRecordDurationMicros int64 = int64((7 * 24 * time.Hour) / time.Microsecond)
|
||||
)
|
||||
|
||||
// Record is deliberately stable and append-log friendly. Sensitive fields are
|
||||
// populated only when explicitly enabled by Policy.
|
||||
type Record struct {
|
||||
@@ -38,7 +43,7 @@ type Record struct {
|
||||
// Validate rejects records that cannot have been produced by this package's
|
||||
// bounded middleware contract.
|
||||
func (record Record) Validate() error {
|
||||
if record.Version != RecordVersion || record.Timestamp.IsZero() || !boundedField(record.Method, 16, false) || !boundedField(record.Route, 256, false) || record.Status < 100 || record.Status > 999 || record.Bytes < 0 || record.DurationMicros < 0 {
|
||||
if record.Version != RecordVersion || record.Timestamp.IsZero() || !boundedField(record.Method, 16, false) || !boundedField(record.Route, 256, false) || record.Status < 100 || record.Status > 999 || record.Bytes < 0 || record.Bytes > maxRecordBytes || record.DurationMicros < 0 || record.DurationMicros > maxRecordDurationMicros {
|
||||
return errors.New("requestlog: invalid record")
|
||||
}
|
||||
fields := []struct {
|
||||
|
||||
@@ -138,6 +138,20 @@ func TestJSONLRejectsInvalidRecord(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRecordRejectsUnboundedNumericFields(t *testing.T) {
|
||||
base := Record{Version: RecordVersion, Timestamp: time.Unix(100, 0), Method: "GET", Route: "home", Status: 200}
|
||||
tooManyBytes := base
|
||||
tooManyBytes.Bytes = maxRecordBytes + 1
|
||||
if err := tooManyBytes.Validate(); err == nil {
|
||||
t.Fatal("unbounded byte count accepted")
|
||||
}
|
||||
tooLong := base
|
||||
tooLong.DurationMicros = maxRecordDurationMicros + 1
|
||||
if err := tooLong.Validate(); err == nil {
|
||||
t.Fatal("unbounded duration accepted")
|
||||
}
|
||||
}
|
||||
|
||||
func TestJSONLRejectsSymlinkDestination(t *testing.T) {
|
||||
if runtime.GOOS == "windows" {
|
||||
t.Skip("symlink creation is privilege-dependent on Windows")
|
||||
|
||||
Reference in New Issue
Block a user