Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .jules/sentinel.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,7 @@
**Vulnerability:** The document hashing routine in `DefaultDocumentConversionService` processed file streams without enforcing any maximum size limit on the bytes read. An attacker could exploit this by uploading a maliciously large stream (or exploiting a compression bomb if unzipping), exhausting system memory, CPU, or disk space (DoS).
**Learning:** Checking the declared file size (e.g., `file.getSize()`) in initial validation is not always sufficient if the input stream itself can be spoofed or dynamically expanded during reading. The actual bytes read must be verified against bounds continuously.
**Prevention:** Always enforce a strict, configurable size limit (e.g., `ConversionProperties.maxUploadSizeBytes`) within the `while` loop that reads from untrusted input streams. Track `totalRead` and throw an exception immediately if the limit is exceeded.
## 2026-08-15 - Remove Environment Variable Fallbacks for Secrets
**Vulnerability:** Runtime secrets were injected from environment variables using placeholders with empty fallbacks, violating the org rule to use a KV registry.
**Learning:** This bypasses strict mounting rules and can silently default to empty strings, which could lead to weak or missing security signatures.
**Prevention:** Remove environment variable fallback syntax from YAML configs and Java `@Value` annotations, enforcing the Spring Boot configtree mounting mechanism.
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,9 @@ public class ArtifactLinkService {
*/
@Autowired
public ArtifactLinkService(
ArtifactStore artifactStore,
ArtifactLinkLedger artifactLinkLedger,
@Value("${clearfolio.artifact-token.secret:}") String configuredSecret) {
final ArtifactStore artifactStore,
final ArtifactLinkLedger artifactLinkLedger,
@Value("${clearfolio.artifact-token.secret}") final String configuredSecret) {
this(artifactStore, artifactLinkLedger, configuredSecret, Clock.systemUTC(), new SecureRandom());
}

Expand All @@ -90,22 +90,22 @@ public ArtifactLinkService(
* @param configuredSecret optional deployment secret
*/
public ArtifactLinkService(
ArtifactStore artifactStore,
String configuredSecret) {
final ArtifactStore artifactStore,
final String configuredSecret) {
this(artifactStore, new ArtifactLinkLedger(), configuredSecret, Clock.systemUTC(), new SecureRandom());
}

ArtifactLinkService(
ArtifactStore artifactStore,
final ArtifactStore artifactStore,
String configuredSecret,
Clock clock,
SecureRandom secureRandom) {
this(artifactStore, new ArtifactLinkLedger(), configuredSecret, clock, secureRandom);
}

ArtifactLinkService(
ArtifactStore artifactStore,
ArtifactLinkLedger artifactLinkLedger,
final ArtifactStore artifactStore,
final ArtifactLinkLedger artifactLinkLedger,
String configuredSecret,
Clock clock,
SecureRandom secureRandom) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,12 @@ public TenantAccessService() {
*/
@Autowired
public TenantAccessService(
@Value("${clearfolio.tenant-claims.hmac-secret:}") String claimsHmacSecret,
@Value("${clearfolio.tenant-claims.max-skew-seconds:300}") long maxSkewSeconds) {
@Value("${clearfolio.tenant-claims.hmac-secret}") final String claimsHmacSecret,
@Value("${clearfolio.tenant-claims.max-skew-seconds:300}") final long maxSkewSeconds) {
this(claimsHmacSecret, maxSkewSeconds, Clock.systemUTC());
}

TenantAccessService(String claimsHmacSecret, long maxSkewSeconds, Clock clock) {
TenantAccessService(final String claimsHmacSecret, final long maxSkewSeconds, final Clock clock) {
this.claimsHmacSecret = clean(claimsHmacSecret);
this.maxSkewSeconds = Math.max(0L, maxSkewSeconds);
this.clock = clock;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ public class ProductionAuthReadinessConfig {
* @param tenantClaimsSecret shared gateway signing secret
*/
public ProductionAuthReadinessConfig(
@Value("${clearfolio.tenant-claims.hmac-secret:}") String tenantClaimsSecret) {
@Value("${clearfolio.tenant-claims.hmac-secret}")
final String tenantClaimsSecret) {
if (!StringUtils.hasText(tenantClaimsSecret)) {
throw new IllegalStateException(
"production profile requires clearfolio.tenant-claims.hmac-secret"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public class ArtifactController {
public ArtifactController(
DocumentConversionService conversionService,
ArtifactStore artifactStore,
ArtifactLinkService artifactLinkService,
final ArtifactLinkService artifactLinkService,
TenantAccessService tenantAccessService) {
this.conversionService = conversionService;
this.artifactStore = artifactStore;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public class ConversionController {
public ConversionController(
DocumentConversionService conversionService,
TenantAccessService tenantAccessService,
ArtifactLinkService artifactLinkService,
final ArtifactLinkService artifactLinkService,
ArtifactStore artifactStore,
@Value("${spring.codec.max-in-memory-size:262144B}") DataSize maxInMemorySize) {
this.conversionService = conversionService;
Expand Down
4 changes: 2 additions & 2 deletions src/main/resources/application-buyer-demo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ viewer:

clearfolio:
artifact-token:
secret: ${CLEARFOLIO_ARTIFACT_TOKEN_SECRET:}
secret: ${CLEARFOLIO_ARTIFACT_TOKEN_SECRET}
tenant-claims:
hmac-secret: ${CLEARFOLIO_TENANT_CLAIMS_HMAC_SECRET:}
hmac-secret: ${CLEARFOLIO_TENANT_CLAIMS_HMAC_SECRET}
max-skew-seconds: ${CLEARFOLIO_TENANT_CLAIMS_MAX_SKEW_SECONDS:300}
artifact-link-ledger:
path: ${CLEARFOLIO_ARTIFACT_LINK_LEDGER_PATH:}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class ProductionAuthReadinessConfigTest {

@Test
void productionProfileFailsWithoutSignedTenantClaimsSecret() {
productionRunner().run(context -> assertThat(context.getStartupFailure())
productionRunner().withPropertyValues("clearfolio.tenant-claims.hmac-secret=").run(context -> assertThat(context.getStartupFailure())
.hasRootCauseMessage("production profile requires clearfolio.tenant-claims.hmac-secret"));
}

Expand Down
Loading