# CubeEgress JSONL Audit Logs: Complete Field Reference and Schema

> Explore CubeEgress JSONL audit logs. This guide details every field and schema, capturing HTTP HTTPS requests, timestamps, IDs, TLS metadata, policy decisions, and security events from TencentCloud CubeSandbox.

- Repository: [Tencent Cloud/CubeSandbox](https://github.com/TencentCloud/CubeSandbox)
- Tags: api-reference
- Published: 2026-07-12

---

**CubeEgress JSONL audit logs capture every HTTP/HTTPS request traversing the transparent proxy as line-delimited JSON records containing timestamps, request IDs, sandbox identity, destination connection details, TLS metadata, HTTP metrics, policy decisions, and security events.**

CubeEgress is the transparent proxy component of the TencentCloud CubeSandbox repository that intercepts outbound traffic from sandboxed workloads. Each request is recorded in `/data/log/cube-egress/access.jsonl` by the Lua module [`CubeEgress/lua/audit.lua`](https://github.com/TencentCloud/CubeSandbox/blob/main/CubeEgress/lua/audit.lua), producing a comprehensive audit trail that includes the policy decision, credential injection actions, and any security-related denials.

## Core Log Fields

### Temporal and Identity Fields

Every log entry begins with precise timing and unique identification. The `ts` field contains an ISO-8601 timestamp in UTC, generated at lines 57-60 of [`CubeEgress/lua/audit.lua`](https://github.com/TencentCloud/CubeSandbox/blob/main/CubeEgress/lua/audit.lua). The `request_id` field provides a unique identifier for the request within the worker, built from `ngx.var.request_id` when available, otherwise constructed from the connection ID and request counter (lines 77-88).

### Network and Connection Metadata

The `sandbox` object identifies the source workload, containing `src_ip` (the sandbox's IP address) and `policy_id` (the UUID of the attached policy). The `conn` field captures the original destination before any routing, exposing `original_dst_ip` and `original_dst_port` (lines 65-68).

### TLS Session Details

For encrypted connections, the `tls` object records the Server Name Indication (`sni`), negotiated cipher suite (`cipher`), TLS protocol version (`version`), and optional client ALPN preferences (lines 69-78). These fields enable compliance auditing and security forensics on HTTPS traffic.

### HTTP Transaction Metrics

The `http` field contains request and response metadata: the HTTP method, target host (`cube_audit_host`), request path (`request_uri`), response status code, byte counts (`req_bytes`, `resp_bytes`), and the User-Agent header (lines 79-87). This data is assembled in `_M.write_one()` to provide complete HTTP visibility.

### Policy Decision and Latency

The `policy` object records which rule matched (`matched_rule`), the final decision (`allow`, `deny`, or `unknown`), and the processing latency in microseconds (`duration_us`). This propagation is defined in [`network-agent/internal/cubeegress/wire.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/network-agent/internal/cubeegress/wire.go) (lines 88-90), allowing operators to audit enforcement actions and performance characteristics.

### Redacted and Reserved Fields

The audit schema includes `redacted_request_headers`, `redacted_request_body`, and `redacted_response_body` fields. These are processed by the helper `redactor` module to ensure sensitive data is stripped. Currently, body fields are always set to `null` and reserved for future "full-audit" modes, while headers are redacted according to configured policies (lines 98-102).

## Security-Specific Records

### Credential Injection Metadata

When a request is allowed and performs secret injection, the `credentials` field lists the header names that were injected and their corresponding secret IDs. Importantly, the actual secret values are never logged, only the metadata required for audit compliance (lines 119-131).

### Security Events and Denials

The `security` field appears only when noteworthy events occur, such as upstream verification failures or injection errors. It contains the `reason` (e.g., `"upstream_unreachable_or_unverified"`, `"secret_not_found"`), along with `inject_dropped` and `inject_skipped` arrays detailing specific header injection failures (lines 45-55).

## Record Types and Event Categories

### Standard HTTP Requests

The default `http_request` record type is emitted by `_M.write_one()` for every proxied request. This comprehensive record merges all core fields into a single JSON line. If a request results in a 502/504 error with zero upstream bytes, the system automatically injects a security reason and emits a separate `security_event` line to ensure the failure is captured (lines 22-55).

### Security Events

Explicit `security_event` records are generated via `_M.write_security_event()` for events that may not survive the normal log phase, such as early connection failures or injection errors. These records repeat critical fields (`sandbox`, `conn`, `tls`, `http`, `credentials`, `policy`, `security`) to guarantee event capture even when the standard request logging path is interrupted (lines 73-84).

### TLS Handshake Failures

When TLS handshakes fail (e.g., certificate validation errors), the system generates `tls_handshake` records containing minimal fields: `ts`, `request_id`, `event`, `sandbox`, `conn`, `tls`, and `security`. This lightweight format ensures compliance logging without exposing incomplete HTTP data (lines 35-45).

## Log Writing Mechanism

### Initialization and File Handling

The audit module initializes with a configurable `FILE_PATH` defaulting to `/data/log/cube-egress/access.jsonl`, configured in [`CubeEgress/nginx.conf`](https://github.com/TencentCloud/CubeSandbox/blob/main/CubeEgress/nginx.conf). During the `init_worker` phase, the module performs a test-open to verify writeability; failure aborts the worker to prevent silent audit loss (lines 34-45). The [`CubeEgress/start.sh`](https://github.com/TencentCloud/CubeSandbox/blob/main/CubeEgress/start.sh) script ensures the host directory exists with proper ownership before container startup.

### Atomic Appends and Concurrency

Per-request logging occurs in the `log_by_lua` phase, which calls `_M.write_one()`. The function constructs the record using `build_record`, encodes it with `cjson.safe`, and atomically appends the line via `io.open(..., "a")`. Writes are atomic because the encoded JSON never exceeds the PIPE_BUF limit (approximately 4 KB), ensuring line integrity under concurrent load (lines 9-21).

## Parsing and Querying Examples

To analyze these logs, you can parse the JSONL format using standard tools. Here is a Go struct matching the audit schema:

```go
type AuditRecord struct {
    Ts        string `json:"ts"`
    RequestID string `json:"request_id"`
    Event     string `json:"event"`
    Sandbox   struct {
        SrcIP    string `json:"src_ip"`
        PolicyID string `json:"policy_id"`
    } `json:"sandbox"`
    Conn struct {
        OriginalDstIP   string `json:"original_dst_ip"`
        OriginalDstPort int    `json:"original_dst_port"`
    } `json:"conn"`
    TLS struct {
        SNI     string `json:"sni"`
        Cipher  string `json:"cipher"`
        Version string `json:"version"`
    } `json:"tls"`
    HTTP struct {
        Method    string `json:"method"`
        Host      string `json:"host"`
        Path      string `json:"path"`
        Status    int    `json:"status"`
        ReqBytes  int    `json:"req_bytes"`
        RespBytes int    `json:"resp_bytes"`
        UserAgent string `json:"user_agent"`
    } `json:"http"`
    Policy struct {
        MatchedRule string `json:"matched_rule"`
        Decision    string `json:"decision"`
        DurationUs  int    `json:"duration_us"`
    } `json:"policy"`
    Credentials *struct {
        Injected  []string `json:"injected"`
        SecretIDs []string `json:"secret_ids"`
    } `json:"credentials,omitempty"`
    Security *struct {
        Reason        string        `json:"reason"`
        InjectDropped string        `json:"inject_dropped"`
        InjectSkipped []interface{} `json:"inject_skipped,omitempty"`
    } `json:"security,omitempty"`
}

```

For command-line analysis, filter denied requests with `jq`:

```bash
grep '"decision":"deny"' /data/log/cube-egress/access.jsonl | jq .

```

You can also write custom security events from Lua:

```lua
local audit = require "audit"
audit.bootstrap({file_path = "/data/log/cube-egress/access.jsonl"})
audit.write_security_event("secret_not_found", {
    policy_id = "sandbox-123",
    rule_id   = "rule-abc",
    allow     = false,
    injected_headers = {}
})

```

## Summary

- CubeEgress writes comprehensive audit records to `/data/log/cube-egress/access.jsonl` in JSONL format via [`CubeEgress/lua/audit.lua`](https://github.com/TencentCloud/CubeSandbox/blob/main/CubeEgress/lua/audit.lua).
- Each record includes temporal data, unique request IDs, sandbox identity (`src_ip`, `policy_id`), connection details (`original_dst_ip`, `original_dst_port`), TLS metadata, and HTTP metrics.
- The `policy` field captures the matched rule, decision (`allow`/`deny`/`unknown`), and latency in microseconds.
- Security events and credential injection metadata are logged without exposing secret values, with dedicated record types for TLS failures and early security events.
- Writes are atomic and safe for concurrent access due to the PIPE_BUF size constraint and `cjson.safe` encoding.

## Frequently Asked Questions

### Where are the audit logs stored?

By default, CubeEgress writes audit logs to `/data/log/cube-egress/access.jsonl`. This path is configured in [`CubeEgress/lua/audit.lua`](https://github.com/TencentCloud/CubeSandbox/blob/main/CubeEgress/lua/audit.lua) via the `FILE_PATH` variable and is ensured to exist by the [`CubeEgress/start.sh`](https://github.com/TencentCloud/CubeSandbox/blob/main/CubeEgress/start.sh) initialization script.

### What sensitive data is redacted from the logs?

The `credentials` field logs only the names of injected headers and their corresponding secret IDs, never the actual secret values. Additionally, the fields `redacted_request_headers`, `redacted_request_body`, and `redacted_response_body` are present but always set to `null` in current implementations, reserved for future "full-audit" modes that would apply redaction rules from the helper `redactor` module.

### How are unique request IDs generated?

The `request_id` field prioritizes `ngx.var.request_id` when available. If the nginx variable is not present, the system generates an identifier by combining the connection ID with an internal request counter, ensuring unique tracking within each worker process.

### Can I write custom security events from my own Lua code?

Yes. The [`CubeEgress/lua/audit.lua`](https://github.com/TencentCloud/CubeSandbox/blob/main/CubeEgress/lua/audit.lua) module exposes `_M.write_security_event()` for external use. You must first call `audit.bootstrap()` with the target file path, then invoke `write_security_event()` with the reason string and relevant metadata to emit a dedicated security event record that persists even if the standard HTTP request logging fails.