ODC Forge: Source-Verified Installation for External Logic Components
50
Views
10
Comments
New
Forge

The Problem

When an External Logic component is published to the Forge today, the author uploads a pre-compiled binary. A git repository link can optionally be included, but it is purely decorative, OutSystems does not verify any relationship between the linked source and the uploaded artifact.

This means that as a consumer, when you install an external logic Forge component, you are executing code you cannot verify. You are trusting the author's word that what they linked on GitHub is what's actually running in your tenant.

This is a real supply-chain risk — even with good intentions, a compromised account, a build-time dependency swap, or a simple mistake can result in consumers running code that doesn't match the published source.

The Proposal

Require that External Logic components submitted to the Forge are cryptographically linked to a public git repository at a specific commit, and that the submission process enforces this linkage — not just documents it optionally.

The flow would look like this:

  1. The publisher develops and uploads their External Logic to their tenant as today (nothing changes here)
  2. When submitting to the Forge, they are required to provide a public git repository URL and a pinned tag or commit SHA that corresponds to the uploaded binary
  3. The Forge stores a SHA-256 checksum of the uploaded artifact alongside the source reference
  4. Consumers can inspect the source at the pinned commit, and optionally build it locally to verify the checksum matches what they'll be installing

This doesn't change the upload mechanics, it adds an auditable envelope around what's already there.

This is the same trust model used by mainstream package ecosystems:

  • go install github.com/user/repo@v1.2.3 — builds from source at a verified tag
  • cargo install --git — fetches and compiles from a git ref
  • crates.io — stores checksums and optionally verifies builds server-side

Why This Matters

  • Transparency: consumers know exactly what code runs in their tenant, down to the commit
  • Supply-chain integrity: eliminates the "binary black box" problem; no more trusting an uploaded artifact blindly
  • Community accountability: published source is public and auditable; the community can catch issues before they spread

O11's Integration Studio was transparent by design, you could open an XIF and see exactly what was there. ODC External Logic moved us forward in capability but took a step back in auditability. This proposal closes that gap, in a modern and supply-chain-secure way.

So, to sum up the current situation:

  1. Anyone can make a free OutSystems Community account, without any actual identity validation
  2. Anyone with said account can upload a Forge (external) library
  3. No-one can see or validate what is inside that library

I'll just leave it at that. I'm lost for words.

@Tim Timperman, exactly. That's the problem this idea is trying to fix, at least for point 3. A pinned git commit + SHA-256 checksum on the uploaded binary would give anyone a way to verify what they're actually installing. Not perfect, but a meaningful step forward.

I made a slightly related idea not so long ago, but the potential risk of your finding is far greater.
https://www.outsystems.com/ideas/15292/allow-download-of-odc-forge-components/


They complement each other. I believe that if your idea was implemented in ODC Portal, it would be a great quick win, at least giving consumers a way to get hold of what they're installing in their tenant and inspect it, rather than installing a complete black box.

Mine goes one step further by trying to tie that artifact back to a verifiable source, but honestly your idea is the more immediate, lower-effort win, and it's actually a prerequisite for the checksum verification I'm proposing, since you can only verify a hash if you can download the binary in the first place.

Hi @Ricardo Monteiro, thanks for submitting this idea and very complete proposal details.


I'm not an expert on checksums, so can you please clarify this for me: when you suggest "build it locally to verify the checksum matches what they'll be installing"  can we be sure we would always get the same checksum or might we face differences? For e.g.: 

  1. can build timestamps alter the checksum? 
  2. or Absolute File Paths? 
  3. or Compiler / SDK Versions?
  4. or Operatings System (re differences on line ending handling)?


If so, is there any way we could configure the project to be reproducible, i.e., replicate the build environment? Would we need to use any specific flags in the .csproj file?

Many thanks once again!

Hi @Fábio Godinho, that's a great question.

Short answer: yes, both timestamps and absolute paths change the hash by default, but .NET's deterministic-build tooling solves it, it's a .csproj concern, not a blocker.

The classic non-determinism sources in a .NET assembly are:

  • PE header TimeDateStamp: historically the wall-clock build time.
  • MVID (Module Version ID): a GUID regenerated on every compile.
  • Embedded absolute paths: source file paths and the PDB path baked into the assembly, which differ per machine/enlistment.

The good news is that Deterministic=true is already the default since .NET Core, which replaces the PE timestamp with a content-derived hash and makes the MVID deterministic. To get byte-for-byte identical output across different machines you additionally need to normalize paths. The minimal .csproj recipe is:

<PropertyGroup>
   <Deterministic>true</Deterministic>
   <ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
   <DebugType>portable</DebugType>
</PropertyGroup>

The first (already default) normalizes the timestamp + MVID; the second normalizes paths. Even simpler: add the DotNet.ReproducibleBuilds package, and pin the SDK with a global.json

Two practical refinements for how the idea should specify this:

  1. Hash the assembly, not the uploaded zip, zip wrappers carry their own timestamps/ordering and would never reproduce.
  2. The hash has to cover the full dependency closure, not just the top-level DLL. This is where it gets real, and I can show it with two of my own components:
    • odc-stage-context has zero external dependencies, a single self-contained DLL. That's the trivial, ideal pilot case: one assembly, reproducible build, one checksum.
    • google-cloud-storage-connector-odc pulls in the official Google.Cloud.Storage .NET SDK and its transitive NuGets, so the shipped External Logic artifact is a bundle of many assemblies. For verification to hold here, the consumer must restore the exact same NuGet versions, and the checksum scheme must cover the whole publish closure, not just the component's own DLL.

So the answer to your question is: build timestamps and absolute paths would break it, but they're fully controllable with standard .csproj settings, and the spec just needs to mandate a reproducible-build configuration, hash the right thing (assemblies, canonicalized), and account for the dependency graph. The zero-dependency case proves it's achievable today; the SDK-wrapping case defines the harder requirements the proposal needs to nail down.

2026-04-26 20-38-42
Paulo Solipa
Champion

@Ricardo Monteiro Hi Ricardo,
Theoretically, by analysing the new OutSystems MCP, it is possible to download the Source Code of an external library. Although this wouldn't solve the issue (I support your idea) it can provide some way to audit the external library code.

Hi @Paulo Solipa, I wasn’t aware of that. Since you mentioned MCP, it means it’s already available through the ODC REST APIs. Great finding ;)

Hey @Ricardo Monteiro so if we were able to download External Logic assets from the ODC Portal, either directly from the Forge or from the Installed assets list, we could see exactly the source code and would give back the auditability you asked, right? And do you think a checksum would still be needed?

Hi @Fábio Godinho yes, downloading the source would give back the auditability, and that alone is a big step forward. But I think a checksum is still needed, because the two solve different problems.

Download = auditability, checksum = verifiability. Download is the quicker win and a great first step; the checksum is what makes the github repo link trustworthy rather than just informative.