Skip to content

fix(EC-1993): reject past --effective-time values by default#3424

Open
cuipinghuo wants to merge 1 commit into
conforma:mainfrom
cuipinghuo:forbid-setting-effective-time
Open

fix(EC-1993): reject past --effective-time values by default#3424
cuipinghuo wants to merge 1 commit into
conforma:mainfrom
cuipinghuo:forbid-setting-effective-time

Conversation

@cuipinghuo

@cuipinghuo cuipinghuo commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Backdating --effective-time suppresses time-gated security rules at both
the CLI level (severity demotion) and the Rego level (when_ns
propagation). Reject effective-time values more than 5 minutes in the
past unless --allow-past-effective-time is explicitly set.

Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com

What:

  • Add validation in parseEffectiveTime() to reject times >5min in the past
  • Add --allow-past-effective-time flag to validate image, validate input, and compare commands
  • 5-minute grace period to accommodate clock skew

Why:

  • Setting --effective-time to a past date demotes time-gated rule failures to warnings (CLI level)
    and shifts the time reference for all Rego rules via when_ns (Rego level), effectively bypassing
    security checks at the integration test gate where users control IntegrationTestScenario params

Tickets:

@fullsend-ai-review

fullsend-ai-review Bot commented Jul 20, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 6:26 PM UTC · Completed 6:31 PM UTC
Commit: 87c4a29 · View workflow run →

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@cuipinghuo, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 49 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d189f3e2-90ba-4670-8fef-a6f9cd3965f6

📥 Commits

Reviewing files that changed from the base of the PR and between 4c43579 and bc38cc2.

📒 Files selected for processing (17)
  • cmd/compare/compare.go
  • cmd/validate/image.go
  • cmd/validate/image_test.go
  • cmd/validate/input.go
  • docs/modules/ROOT/pages/ec_compare.adoc
  • docs/modules/ROOT/pages/ec_validate_image.adoc
  • docs/modules/ROOT/pages/ec_validate_input.adoc
  • docs/modules/ROOT/pages/verify-conforma-konflux-ta.adoc
  • docs/modules/ROOT/pages/verify-enterprise-contract.adoc
  • features/task_validate_image.feature
  • features/validate_image.feature
  • internal/input/report_test.go
  • internal/input/validate_test.go
  • internal/policy/policy.go
  • internal/policy/policy_test.go
  • tasks/verify-conforma-konflux-ta/0.1/verify-conforma-konflux-ta.yaml
  • tasks/verify-enterprise-contract/0.1/verify-enterprise-contract.yaml
📝 Walkthrough

Walkthrough

The change adds --allow-past-effective-time to comparison and validation commands, propagates the option through policy and Tekton task configuration, and rejects timestamps older than five minutes unless explicitly allowed. Tests and documentation cover parsing, constructors, command execution, and task scenarios.

Changes

Past effective-time allowance

Layer / File(s) Summary
Policy parsing and constructors
internal/policy/policy.go, internal/policy/policy_test.go
Policy options and constructors propagate past-time allowance; parsing applies a five-minute grace period, corrects chosen-time state, and tests cover accepted and rejected timestamps.
CLI flags and policy wiring
cmd/compare/compare.go, cmd/validate/image.go, cmd/validate/input.go, cmd/validate/image_test.go
Commands register --allow-past-effective-time, pass it into policy handling, and update command coverage.
Tekton task propagation
tasks/verify-conforma-konflux-ta/..., tasks/verify-enterprise-contract/...
Task parameters and validate-step wiring pass the allowance to the Conforma CLI.
Scenario coverage and documentation
internal/input/*_test.go, features/*.feature, docs/modules/ROOT/pages/*
Constructor calls, feature scenarios, and command and task documentation reflect the new behavior.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant TektonTask
  participant CLI
  participant Policy
  participant EffectiveTimeParser
  TektonTask->>CLI: pass --allow-past-effective-time
  CLI->>Policy: provide allowance and effective time
  Policy->>EffectiveTimeParser: parse and validate timestamp
  EffectiveTimeParser-->>Policy: accept or reject timestamp
  Policy-->>CLI: return policy or parsing result
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 31.25% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the main change: rejecting past effective-time values by default with an opt-out flag.
Description check ✅ Passed The description follows the template with What, Why, and Tickets sections and includes the key context for the change.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@fullsend-ai-review

fullsend-ai-review Bot commented Jul 20, 2026

Copy link
Copy Markdown

Review

Findings

High

  • [breaking-cli] tasks/verify-enterprise-contract/0.1/verify-enterprise-contract.yaml:383 — The Tekton tasks (both verify-enterprise-contract and verify-conforma-konflux-ta) are modified in-place at version 0.1 with a breaking behavioral change. Existing pipelines that set EFFECTIVE_TIME to a past date without also setting ALLOW_PAST_EFFECTIVE_TIME=true will start failing after consuming this update. Modifying a shipped task version in-place risks silent breakage for pinned consumers.
    Remediation: Consider bumping the Tekton task to a new version (e.g. 0.2) so existing pipelines pinned to 0.1 are unaffected, or prominently document the migration path in release notes.

Medium

  • [breaking-cli] cmd/validate/image.go — The CLI now rejects --effective-time values more than 5 minutes in the past by default across validate image, validate input, and compare commands. Any CI/CD scripts or wrappers that pass past dates will break without adding --allow-past-effective-time. This is intentional security hardening but constitutes a breaking behavioral change that requires release notes.
    Remediation: Ensure release notes clearly document the behavioral change and the --allow-past-effective-time escape hatch.

  • [scope-creep] internal/policy/policy.go — The PR introduces a new exported function ParseEffectiveTime that wraps the internal parseEffectiveTime. It is only consumed by cmd/compare/compare.go. Exporting a low-level parsing function breaks the established pattern where all exports in this file are constructors (New*) or high-level operations (Validate*, PreProcess*).
    Remediation: Consider having compare.go use NewOfflinePolicy or NewPolicy instead, or document why the existing constructors are insufficient for the compare use case.

  • [error-handling-idiom] internal/policy/policy.go — The rejectPastTime function produces "effective time %s is in the past; use --allow-past-effective-time to override", embedding a CLI flag name in an internal/ package. All existing fmt.Errorf messages in this file use generic, CLI-agnostic phrasing (e.g., "invalid policy time argument"). This couples the library to the CLI's flag naming.
    Remediation: Return a generic error (e.g., "effective time %s is in the past") and let the CLI layer annotate the error with the flag hint.

  • [fail-open] tasks/verify-conforma-konflux-ta/0.1/verify-conforma-konflux-ta.yaml:438ALLOW_PAST_EFFECTIVE_TIME Tekton parameter is type: string with default "false", passed as --allow-past-effective-time="${ALLOW_PAST_EFFECTIVE_TIME}". Tekton has no native boolean type, so no input validation occurs at the parameter level. However, Go's strconv.ParseBool (used by cobra BoolVar) rejects invalid strings with an error — the behavior is fail-closed for malformed input. Acceptable; no action needed.

Low

  • [stale-doc] cmd/compare/README.md:26 — Missing --allow-past-effective-time flag and stale --effective-time description. The canonical .adoc docs were updated.
  • [stale-doc] cmd/compare/README.md:56 — Examples use past dates that would now be rejected without --allow-past-effective-time.
  • [missing-doc] tasks/verify-enterprise-contract/0.1/README.md:41 — Missing ALLOW_PAST_EFFECTIVE_TIME parameter (canonical .adoc docs were updated).
  • [missing-doc] tasks/verify-conforma-konflux-ta/0.1/README.md:32 — Missing ALLOW_PAST_EFFECTIVE_TIME parameter (canonical .adoc docs were updated).
  • [scope-creep] internal/policy/policy.go — The choosenTimechosenTime rename is unrelated to EC-1993 and inflates the diff. Consider splitting into a separate PR.
  • [code-organization] cmd/validate/input.go:48allowPastEffectiveTime field placement differs between input.go (grouped with effectiveTime) and image.go (alphabetical).
  • [edge-case] cmd/compare/compare.go:96 — When --effective-time=attestation is used with compare, it silently falls back to current time via IsZero(). Pre-existing behavior preserved by this PR.
  • [function-signature] internal/policy/policy.goNewOfflinePolicy hardcodes allowPast=true without an explanatory comment, unlike NewInputPolicy and NewPolicy which accept the parameter.
Previous run

Review

Findings

High

  • [consumer-completeness] cmd/validate/vsa.go:405 — The validate vsa command constructs policy.Options{} with EffectiveTime but does not set AllowPastEffectiveTime (defaults to false). After this PR, any past effective time passed via --effective-time to ec validate vsa will be rejected, and there is no --allow-past-effective-time flag added to the VSA command to override this. This is an unintentional behavior change — the VSA command silently gains the restriction without providing the escape hatch.
    Remediation: Add --allow-past-effective-time flag to the VSA command (in cmd/validate/vsa.go) and wire it into the policy.Options struct, mirroring the pattern used in cmd/validate/image.go and cmd/validate/input.go.

  • [consumer-completeness] internal/validate/vsa/fallback.go:122 — The fallback validation context constructs policy.Options{} with config.EffectiveTime but does not set AllowPastEffectiveTime. The FallbackConfig struct does not include an AllowPastEffectiveTime field, so there is no way to propagate this setting to fallback validation.
    Remediation: Add AllowPastEffectiveTime to the FallbackConfig struct, propagate the value from the VSA command, and include it in the policy.Options at fallback.go:122.

  • [breaking-cli] internal/policy/policy.go:457 — The default behavior of --effective-time is changed in a backward-incompatible way. Past dates are now rejected unless --allow-past-effective-time is also passed. Any downstream CI/CD pipeline or script using ec validate image --effective-time <past-date> will start failing after upgrading the CLI binary. The Tekton tasks in this repo are updated, but external pipelines, automation scripts, or other repositories that shell out to the ec CLI with past effective times will break silently upon CLI upgrade.
    Remediation: Document this as a breaking change in release notes and consider bumping the minor/major version to signal the behavioral change to downstream consumers. At minimum, release notes must prominently call out that existing --effective-time invocations with past dates will now fail.

Medium

  • [security-bypass-tekton] tasks/verify-enterprise-contract/0.1/verify-enterprise-contract.yaml — The ALLOW_PAST_EFFECTIVE_TIME Tekton parameter is typed as string with default "false". Any pipeline operator who can configure pipeline parameters can set it to "true" to bypass the past-time rejection security control. The parameter description should include a security warning noting that enabling this bypasses time-gating protection. See also: [breaking-config] finding for this file.
    Remediation: Add a security note in the parameter description, e.g., "SECURITY: Enabling this allows bypassing time-gated policy rules."

  • [scope-creep] internal/policy/policy.go:437 — The PR introduces a new exported function policy.ParseEffectiveTime() that has the same name as the existing vsa.ParseEffectiveTime() in internal/validate/vsa/validator.go with a different signature and different behavior (the VSA version has no past-time rejection, no date-only format, and no "attestation" sentinel). Having two exported functions with the same name but different behavior creates developer confusion.
    Remediation: Consider documenting the relationship or filing a follow-up to unify the two functions.

  • [breaking-config] tasks/verify-enterprise-contract/0.1/verify-enterprise-contract.yaml:162 — The new ALLOW_PAST_EFFECTIVE_TIME parameter is added to the existing 0.1 version of both Tekton tasks rather than creating a 0.2 version. Combined with the behavioral change to --effective-time, existing pipelines using EFFECTIVE_TIME with past dates will break when they pick up the new task bundle. See also: [security-bypass-tekton] finding for this file.
    Remediation: Either introduce this as a 0.2 version of the task, or set ALLOW_PAST_EFFECTIVE_TIME default to "true" initially for backward compatibility and change the default to "false" in a later version bump.

Low

  • [edge-case] internal/policy/policy.go:183NewOfflinePolicy unconditionally passes allowPast=true to parseEffectiveTime. This is by design (offline mode has no attack surface from parameter injection), but worth documenting the security rationale. Verified: callers are test files and definition.go which always passes "now".

  • [naming-convention] internal/policy/policy.go:435 — The parameter name choosenTime perpetuates the existing misspelling (should be chosenTime) in the new exported ParseEffectiveTime function. While the typo exists in internal code, the new exported function is an opportunity to use the correct spelling.

  • [flag-declaration-style] cmd/compare/compare.go:77 — The --allow-past-effective-time flag description in compare.go omits "By default, dates more than 5 minutes in the past are rejected" which is present in image.go and input.go. Consistent help text across commands would be preferable.

  • [attestation-bypass] internal/policy/policy.go — When effectiveTime is "attestation", parseEffectiveTime returns nil and rejectPastTime is never called. AttestationTime() directly assigns p.effectiveTime without past-time validation. The attestation path relies on signature verification as its security boundary rather than temporal validation.

  • [grace-period] internal/policy/policy.go — The 5-minute grace period is a reasonable UX trade-off for clock skew. Worth documenting in the security model.

  • [struct-field-ordering] cmd/validate/image.go:639 — The new allowPastEffectiveTime field is placed after effectiveTime, breaking the alphabetical ordering convention used by the imageData struct.

  • [api-contract] cmd/compare/compare.go:92 — The "attestation" sentinel is accepted by --effective-time but not documented in the compare command's help text. Pre-existing condition, not introduced by this PR.

  • [scope] cmd/compare/compare.go:89 — The compare command refactoring replaces inline time parsing with ParseEffectiveTime. This is a behavioral change beyond the stated fix scope — previously compare accepted any past time silently.

Previous run (2)

Review

Findings

Medium

  • [duplicate-validation-logic] cmd/compare/compare.go:100 — The compare command implements its own past-time rejection logic inline using time.Now().UTC() and a hardcoded 5-minute grace period, duplicating the centralized rejectPastTime() function in internal/policy/policy.go. The validate image and validate input commands correctly delegate to parseEffectiveTimerejectPastTime, but the compare command bypasses this path. This creates three maintenance risks: (1) the inline check uses the real wall clock instead of the testable now var, making the compare path untestable with mocked clocks; (2) the grace period is hardcoded rather than referencing pastEffectiveTimeGracePeriod, so the two could drift; (3) the compare command only handles RFC3339 format, while parseEffectiveTime also handles date-only format ("2006-01-02").
    Remediation: Refactor runCompare to use parseEffectiveTime (or at minimum rejectPastTime) from internal/policy instead of reimplementing the past-time check inline.

Labels: PR is a security fix (EC-1993, Red Team findings F7-1/F7-2) that modifies CLI command implementations

Previous run (3)

Review — comment

PR: fix(EC-1993): reject past --effective-time values by default

Summary

This PR adds a security mitigation to prevent users from backdating --effective-time to values more than 5 minutes in the past, which could suppress time-gated security rules at both the CLI level (severity demotion) and the Rego level (when_ns propagation). A new --allow-past-effective-time boolean flag provides an explicit override.

The core logic in internal/policy/policy.go is well-structured: a dedicated rejectPastTime function, a pastEffectiveTimeGracePeriod constant, and clean integration into both RFC3339 and date-only parse paths. The flag is consistently wired through all three commands (validate image, validate input, compare). Test coverage for the core behavior in TestParseEffectiveTimePastRejection is thorough and covers boundary conditions.

Findings

1. Duplicate effective-time validation in compare.go — medium / correctness

cmd/compare/compare.go implements its own past-time rejection logic (diff lines 100–105) independently from the shared rejectPastTime function and pastEffectiveTimeGracePeriod constant in internal/policy/policy.go:

// compare.go — inline, untestable
threshold := time.Now().UTC().Add(-5 * time.Minute)

// policy.go — shared constant, mockable clock
threshold := now().UTC().Add(-pastEffectiveTimeGracePeriod)

This creates two maintenance concerns:

  1. Duplicated threshold: The 5-minute window is a constant in policy.go but hardcoded inline in compare.go. Future threshold changes must be updated in two places, with no compiler or test to catch a drift.
  2. Untestable clock: compare.go calls time.Now() directly instead of the package-level now() function from the policy package, making it impossible to mock time in tests. There is no test coverage for this new validation path in compare.go.

Remediation: Consider refactoring compare.go to delegate effective-time parsing to a shared utility (e.g., exporting ParseAndValidateEffectiveTime from the policy package), or at minimum reference the existing constant and add test coverage for the compare command's validation path.

Positive observations

  • The rejectPastTime function in policy.go is clean, well-placed, and called from both the RFC3339 and date-only parse paths.
  • NewOfflinePolicy correctly passes allowPast: true, preserving backward compatibility for offline scenarios that may need arbitrary time evaluation.
  • All NewInputPolicy call sites (including internal/input/report_test.go, internal/input/validate_test.go, and internal/policy/policy_test.go) are updated consistently with the new parameter.
  • The Options struct uses the zero value (false) as the safe default for AllowPastEffectiveTime, so existing callers of NewPolicy get the restrictive behavior automatically.
  • TestParseEffectiveTimePastRejection provides comprehensive coverage: past dates rejected, grace period boundaries, allowPast=true override, future dates accepted, and "now"/"attestation" unaffected.
  • Existing tests that use past dates (e.g., TestNewPolicy, TestPreProcessPolicy) are correctly updated with AllowPastEffectiveTime: true.

fullsend-ai-review[bot]

This comment was marked as outdated.

@fullsend-ai-review fullsend-ai-review Bot added the requires-manual-review Review requires human judgment label Jul 20, 2026
@cuipinghuo
cuipinghuo force-pushed the forbid-setting-effective-time branch from 3c390e7 to b09a732 Compare July 21, 2026 13:22
@fullsend-ai-review

fullsend-ai-review Bot commented Jul 21, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 1:22 PM UTC · Completed 1:43 PM UTC
Commit: 87c4a29 · View workflow run →

@fullsend-ai-review

fullsend-ai-review Bot commented Jul 21, 2026

Copy link
Copy Markdown

🤖 Review · ❌ Terminated · Started 5:46 PM UTC · Ended 6:08 PM UTC
Commit: 87c4a29 · View workflow run →

@codecov

codecov Bot commented Jul 21, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 83.58209% with 11 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
internal/policy/policy.go 80.55% 7 Missing ⚠️
cmd/compare/compare.go 33.33% 4 Missing ⚠️
Flag Coverage Δ
acceptance 54.31% <74.62%> (+0.05%) ⬆️
generative 16.77% <0.00%> (-0.03%) ⬇️
integration 27.99% <35.82%> (+0.02%) ⬆️
unit 71.78% <80.59%> (+0.03%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
cmd/validate/image.go 91.31% <100.00%> (+0.10%) ⬆️
cmd/validate/input.go 95.45% <100.00%> (+0.07%) ⬆️
cmd/compare/compare.go 35.16% <33.33%> (+2.87%) ⬆️
internal/policy/policy.go 90.14% <80.55%> (-1.60%) ⬇️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

fullsend-ai-review[bot]

This comment was marked as outdated.

@fullsend-ai-review fullsend-ai-review Bot removed the requires-manual-review Review requires human judgment label Jul 21, 2026
@fullsend-ai-review

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 5:46 PM UTC · Completed 6:08 PM UTC
Commit: 87c4a29 · View workflow run →

@cuipinghuo
cuipinghuo force-pushed the forbid-setting-effective-time branch from 68ae46f to 4c43579 Compare July 24, 2026 13:51
@fullsend-ai-review

fullsend-ai-review Bot commented Jul 24, 2026

Copy link
Copy Markdown

🤖 Review · ⚠️ Cancelled · Started 1:52 PM UTC · Ended 2:02 PM UTC
Commit: 87c4a29 · View workflow run →

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
internal/policy/policy.go (1)

86-96: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Struct field alignment broken by rename (fails gofmt).

chosenTime (renamed from choosenTime) is now misaligned relative to the other struct fields, which is why the formatter check fails at line 89.

🔧 Proposed fix
 type policy struct {
 	ecc.EnterpriseContractPolicySpec
 	checkOpts         *cosign.CheckOpts
-	chosenTime       string
+	chosenTime        string
 	effectiveTime     *time.Time
 	attestationTime   *time.Time
 	identity          cosign.Identity
 	ignoreRekor       bool
 	skipImageSigCheck bool
 	skipAttSigCheck   bool
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/policy/policy.go` around lines 86 - 96, Align the chosenTime field
declaration in the policy struct with the surrounding fields and run gofmt on
the file, preserving the corrected spelling from choosenTime.

Source: Linters/SAST tools

🧹 Nitpick comments (1)
internal/policy/policy_test.go (1)

247-253: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Cover default-deny propagation through constructors. All historical-time constructor tests force allowance on. Parser tests alone cannot detect a wrapper that ignores or misroutes the flag.

  • internal/policy/policy_test.go#L247-L253: add a past-time NewPolicy case with AllowPastEffectiveTime: false that expects rejection.
  • internal/policy/policy_test.go#L1206-L1206: parameterize allowance and test NewInputPolicy rejects a past timestamp when false.
  • internal/policy/policy_test.go#L1377-L1438: add a PreProcessPolicy default-deny case.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/policy/policy_test.go` around lines 247 - 253, Add default-deny
constructor coverage in internal/policy/policy_test.go: in the NewPolicy case
around lines 247-253, add AllowPastEffectiveTime: false and assert past-time
creation is rejected; parameterize the NewInputPolicy test around line 1206 to
verify rejection when allowance is false; and add a corresponding
PreProcessPolicy default-deny case in lines 1377-1438, while preserving the
existing allow=true cases.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/policy/policy_test.go`:
- Line 801: Restore gofmt formatting for the chosenTime field in the affected
test struct, aligning it with the surrounding fields, then run gofmt on the file
to ensure the formatter check passes.

In `@internal/policy/policy.go`:
- Around line 446-482: Update parseEffectiveTime so both time.Parse failures are
retained instead of shadowing the outer err variable. Use distinct parse-error
assignments or otherwise preserve the RFC3339 error before joining the
DateFormat error, and return the combined errors in the existing invalid policy
time message.

---

Outside diff comments:
In `@internal/policy/policy.go`:
- Around line 86-96: Align the chosenTime field declaration in the policy struct
with the surrounding fields and run gofmt on the file, preserving the corrected
spelling from choosenTime.

---

Nitpick comments:
In `@internal/policy/policy_test.go`:
- Around line 247-253: Add default-deny constructor coverage in
internal/policy/policy_test.go: in the NewPolicy case around lines 247-253, add
AllowPastEffectiveTime: false and assert past-time creation is rejected;
parameterize the NewInputPolicy test around line 1206 to verify rejection when
allowance is false; and add a corresponding PreProcessPolicy default-deny case
in lines 1377-1438, while preserving the existing allow=true cases.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c7f3ee75-86e1-46e5-8659-606bb809fa74

📥 Commits

Reviewing files that changed from the base of the PR and between 68ae46f and 4c43579.

📒 Files selected for processing (17)
  • cmd/compare/compare.go
  • cmd/validate/image.go
  • cmd/validate/image_test.go
  • cmd/validate/input.go
  • docs/modules/ROOT/pages/ec_compare.adoc
  • docs/modules/ROOT/pages/ec_validate_image.adoc
  • docs/modules/ROOT/pages/ec_validate_input.adoc
  • docs/modules/ROOT/pages/verify-conforma-konflux-ta.adoc
  • docs/modules/ROOT/pages/verify-enterprise-contract.adoc
  • features/task_validate_image.feature
  • features/validate_image.feature
  • internal/input/report_test.go
  • internal/input/validate_test.go
  • internal/policy/policy.go
  • internal/policy/policy_test.go
  • tasks/verify-conforma-konflux-ta/0.1/verify-conforma-konflux-ta.yaml
  • tasks/verify-enterprise-contract/0.1/verify-enterprise-contract.yaml
🚧 Files skipped from review as they are similar to previous changes (15)
  • tasks/verify-enterprise-contract/0.1/verify-enterprise-contract.yaml
  • cmd/validate/image_test.go
  • docs/modules/ROOT/pages/ec_validate_input.adoc
  • tasks/verify-conforma-konflux-ta/0.1/verify-conforma-konflux-ta.yaml
  • docs/modules/ROOT/pages/ec_compare.adoc
  • internal/input/report_test.go
  • cmd/validate/image.go
  • features/task_validate_image.feature
  • cmd/validate/input.go
  • cmd/compare/compare.go
  • docs/modules/ROOT/pages/verify-enterprise-contract.adoc
  • docs/modules/ROOT/pages/ec_validate_image.adoc
  • docs/modules/ROOT/pages/verify-conforma-konflux-ta.adoc
  • features/validate_image.feature
  • internal/input/validate_test.go

Comment thread internal/policy/policy_test.go Outdated
Comment thread internal/policy/policy.go
Backdating --effective-time suppresses time-gated security rules at both
the CLI level (severity demotion) and the Rego level (when_ns
propagation). Reject effective-time values more than 5 minutes in the
past unless --allow-past-effective-time is explicitly set.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

What:
- Add validation in parseEffectiveTime() to reject times >5min in the past
- Add --allow-past-effective-time flag to validate image, validate input, and compare commands
- Add ALLOW_PAST_EFFECTIVE_TIME param to Tekton tasks
- Export ParseEffectiveTime() from policy package; compare command delegates to it
- 5-minute grace period to accommodate clock skew

Why:
- Setting --effective-time to a past date demotes time-gated rule failures to warnings (CLI level)
  and shifts the time reference for all Rego rules via when_ns (Rego level), effectively bypassing
  security checks at the integration test gate where users control IntegrationTestScenario params

Tickets:
- https://redhat.atlassian.net/browse/EC-1993
- Ref: EC-1843 (Red Team findings F7-1 and F7-2)

BREAKING CHANGE: --effective-time no longer accepts dates more than 5 minutes in
the past. Users who relied on backdating must now also pass
--allow-past-effective-time (CLI) or set ALLOW_PAST_EFFECTIVE_TIME=true (Tekton
task param). The default value "now" and "attestation" are unaffected.
@cuipinghuo
cuipinghuo force-pushed the forbid-setting-effective-time branch from 4c43579 to bc38cc2 Compare July 24, 2026 14:01
@fullsend-ai-review

fullsend-ai-review Bot commented Jul 24, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 2:02 PM UTC · Completed 2:23 PM UTC
Commit: 87c4a29 · View workflow run →

@fullsend-ai-review fullsend-ai-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the review comment for full details.

@@ -379,6 +383,7 @@ spec:
--show-successes=true

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[high] breaking-cli

The Tekton tasks (both verify-enterprise-contract and verify-conforma-konflux-ta) are modified in-place at version 0.1 with a breaking behavioral change. Existing pipelines that set EFFECTIVE_TIME to a past date without also setting ALLOW_PAST_EFFECTIVE_TIME=true will start failing. Modifying a shipped task version in-place risks silent breakage for pinned consumers.

Suggested fix: Consider bumping the Tekton task to a new version (e.g. 0.2) so existing pipelines pinned to 0.1 are unaffected, or prominently document the migration path in release notes.

--show-successes=true
--show-policy-docs-link=true
--effective-time="${EFFECTIVE_TIME}"
--allow-past-effective-time="${ALLOW_PAST_EFFECTIVE_TIME}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[medium] fail-open

ALLOW_PAST_EFFECTIVE_TIME Tekton parameter is type:string with default 'false'. Tekton has no input validation, but Go's strconv.ParseBool rejects invalid strings with an error (fail-closed). Acceptable behavior.

Comment thread cmd/validate/input.go
serverPort int
effectiveTime string
allowPastEffectiveTime bool
filePaths []string

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[low] code-organization

allowPastEffectiveTime field placement differs between input.go (grouped with effectiveTime) and image.go (alphabetical). Inconsistent ordering convention.

Comment thread cmd/compare/compare.go
if err != nil {
return fmt.Errorf("invalid effective time format: %w", err)
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[low] edge-case

When --effective-time=attestation is used with compare, ParseEffectiveTime returns a zero time.Time and the IsZero() check falls back to time.Now().UTC(). Pre-existing behavior preserved by this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant