Improvements to policy handling (#3595)

* Use webpack loaders to generate both the pug output and the SHA256 hash of it
* Uniformly use pug for HTML templating
* Policy hashes are entirely client-side
* No longer need to have the policy documents available to the server side
This commit is contained in:
Matt Godbolt
2022-04-28 15:19:06 -05:00
committed by GitHub
parent 7828576a5b
commit 58337bb5bf
13 changed files with 299 additions and 429 deletions

7
app.js
View File

@@ -657,13 +657,6 @@ async function main() {
);
};
// Always serve the generated context directly from the distPath.
router.use(
'/static/generated',
express.static(path.join(distPath, 'static', 'generated'), {
maxAge: staticMaxAgeSecs * 1000,
}),
);
await (isDevMode() ? setupWebPackDevMiddleware(router) : setupStaticMiddleware(router));
morgan.token('gdpr_ip', req => (req.ip ? utils.anonymizeIp(req.ip) : ''));

View File

@@ -0,0 +1,30 @@
import {execSync} from 'child_process';
import {getHashDigest} from 'loader-utils';
import * as pug from 'pug';
function execGit(command) {
const gitResult = execSync(command);
if (!gitResult) {
throw new Error(`Failed to execute ${command}`);
}
return gitResult.toString();
}
const gitChanges = execGit('git log --date=local --after="3 months ago" "--grep=(#[0-9]*)" --oneline')
.split('\n')
.map(line => line.match(/(?<hash>\w+) (?<description>.*)/))
.filter(x => x)
.map(match => match.groups);
export default function(content) {
const filename = this.resourcePath;
const lastTime = execGit(`git log -1 --format=%cd "${filename}"`).trimEnd();
const lastCommit = execGit(`git log -1 --format=%h "${filename}"`).trimEnd();
const compiled = pug.compile(content.toString(), {filename});
const source = compiled({gitChanges, lastTime, lastCommit});
const result = {
hash: getHashDigest(source, 'sha256', 'hex', 16),
text: source.toString(),
};
return `export default ${JSON.stringify(result)};`;
}

View File

@@ -30,9 +30,7 @@ import _ from 'underscore';
import {logger} from './logger';
import {getToolTypeByKey} from './tooling';
import {asSafeVer, countOccurrences, getHash, resolvePathFromAppRoot, splitArguments} from './utils';
const HashVersion = 'Compiler Explorer Policies Version 1';
import {asSafeVer, getHash, splitArguments} from './utils';
/***
* Handles the setup of the options object passed on each page request
@@ -113,21 +111,10 @@ export class ClientOptionsHandler {
policies: {
cookies: {
enabled: cookiePolicyEnabled,
hash: cookiePolicyEnabled
? ClientOptionsHandler.getFileHash(
resolvePathFromAppRoot('static', 'generated', 'cookies.html'),
)
: null,
key: 'cookie_status',
},
privacy: {
enabled: privacyPolicyEnabled,
hash: privacyPolicyEnabled
? ClientOptionsHandler.getFileHash(
resolvePathFromAppRoot('static', 'generated', 'privacy.html'),
)
: null,
// How we store this privacy hash on the local storage
key: 'privacy_status',
},
},
@@ -390,13 +377,4 @@ export class ClientOptionsHandler {
getHash() {
return this.optionsHash;
}
static getFileHash(path) {
if (!fs.existsSync(path)) {
logger.error(`File ${path} requested for hashing not found`);
// Should we throw? What should happen here?
}
return getHash(fs.readFileSync(path, 'utf-8'), HashVersion);
}
}

76
package-lock.json generated
View File

@@ -29,7 +29,6 @@
"file-saver": "^2.0.5",
"fs-extra": "^10.0.0",
"golden-layout": "^1.5.9",
"handlebars": "^4.7.7",
"html-loader": "^3.0.1",
"http-proxy": "^1.18.1",
"husky": "^7.0.4",
@@ -6927,34 +6926,6 @@
"integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==",
"dev": true
},
"node_modules/handlebars": {
"version": "4.7.7",
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz",
"integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==",
"dependencies": {
"minimist": "^1.2.5",
"neo-async": "^2.6.0",
"source-map": "^0.6.1",
"wordwrap": "^1.0.0"
},
"bin": {
"handlebars": "bin/handlebars"
},
"engines": {
"node": ">=0.4.7"
},
"optionalDependencies": {
"uglify-js": "^3.1.4"
}
},
"node_modules/handlebars/node_modules/source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/har-schema": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
@@ -14039,18 +14010,6 @@
"node": ">=4.2.0"
}
},
"node_modules/uglify-js": {
"version": "3.15.4",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.15.4.tgz",
"integrity": "sha512-vMOPGDuvXecPs34V74qDKk4iJ/SN4vL3Ow/23ixafENYvtrNvtbcgUeugTcUGRGsOF/5fU8/NYSL5Hyb3l1OJA==",
"optional": true,
"bin": {
"uglifyjs": "bin/uglifyjs"
},
"engines": {
"node": ">=0.8.0"
}
},
"node_modules/unbox-primitive": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",
@@ -15075,11 +15034,6 @@
"node": ">=0.10.0"
}
},
"node_modules/wordwrap": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
"integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus="
},
"node_modules/workerpool": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz",
@@ -20525,25 +20479,6 @@
"integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==",
"dev": true
},
"handlebars": {
"version": "4.7.7",
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz",
"integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==",
"requires": {
"minimist": "^1.2.5",
"neo-async": "^2.6.0",
"source-map": "^0.6.1",
"uglify-js": "^3.1.4",
"wordwrap": "^1.0.0"
},
"dependencies": {
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
}
}
},
"har-schema": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
@@ -25833,12 +25768,6 @@
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.2.tgz",
"integrity": "sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg=="
},
"uglify-js": {
"version": "3.15.4",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.15.4.tgz",
"integrity": "sha512-vMOPGDuvXecPs34V74qDKk4iJ/SN4vL3Ow/23ixafENYvtrNvtbcgUeugTcUGRGsOF/5fU8/NYSL5Hyb3l1OJA==",
"optional": true
},
"unbox-primitive": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",
@@ -26588,11 +26517,6 @@
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ=="
},
"wordwrap": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
"integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus="
},
"workerpool": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz",

View File

@@ -40,7 +40,6 @@
"file-saver": "^2.0.5",
"fs-extra": "^10.0.0",
"golden-layout": "^1.5.9",
"handlebars": "^4.7.7",
"html-loader": "^3.0.1",
"http-proxy": "^1.18.1",
"husky": "^7.0.4",

View File

@@ -1,9 +0,0 @@
<div class="commits-list">
{{#each gitChanges}}
<div class="row commit-entry">
<div class="col-sm-12">
<a href="https://github.com/compiler-explorer/compiler-explorer/commit/{{hash}}" rel="noreferrer noopener" target="_blank">{{description}}</a>
</div>
</div>
{{/each}}
</div>

View File

@@ -0,0 +1,6 @@
div.commits-list
each change in gitChanges
div.row.commit-entry
div.col-sm-12
a(href="https://github.com/compiler-explorer/compiler-explorer/commit/#{change.hash}"
rel="noreferrer noopener" target="_blank") #{change.description}

View File

@@ -1,78 +0,0 @@
<!DOCTYPE html>
<!--
Be aware: modifying this file in any way will cause a pop-up to users telling them the cookie policy has changed.
-->
<html lang="en">
<body>
<!--
No need to update this! It's done by the build process.
-->
<span id="last-changed">
Last changed on: <time id="changed-date" datetime="{{lastTime}}">{{lastTime}}</time>
<i>
(<a href="https://github.com/compiler-explorer/compiler-explorer/commit/{{lastCommit}}" target="_blank">diff</a>)
</i>
</span>
<h2>Compiler Explorer Cookie Policy</h2>
<p>
Browsers support the storing and sending back of small text files called "Cookies". These cookie files can be used
(amongst other things) to help track the usage of a website. See
<a href="https://developer.mozilla.org/docs/Web/HTTP/Cookies" target="_blank" rel="noreferrer noopener">the Mozilla
description of cookies</a> for more details.
</p>
<p>
Compiler Explorer uses Google Analytics, which in turn uses cookies. Google Analytics allows us to see how many
individual users of Compiler Explorer there are, how often users visit us, the average amount of time spent on the
site, the frequency and distribution of compilers selected, and so on. It is invaluable in helping us make
decisions in prioritising work on the site. It's important to note that these cookies are anonymous: we don't know
who each individual user is. Our Google Analytics settings prevent data being retained for more than 14 months. The
cookie stored is a first party cookie: you will find it in your browser under "godbolt.org" cookies.
</p>
<p>
Your privacy is important to us, and you may opt out of this tracking at any time using the buttons on this dialog,
with no loss of access or functionality of Compiler Explorer.
</p>
<h2><span style="color: darkslategray">Necessary</span> Local Storage</h2>
<p>
To store your preferred options between sessions, such as your input code and user interface layout, we make use of
your browser's local storage, where we place:
</p>
<ul>
<li>The current page state, such as:
<ul>
<li>Your current code</li>
<li>Selected compilers and their options</li>
<li>Pane layout</li>
<li>Font sizes</li>
</ul>
</li>
<li>Your settings as shown in the settings popup (which can be found at: More > Settings), such as:
<ul>
<li>Your theme selection</li>
<li>The default language</li>
<li>Compile-as-you-type settings</li>
</ul>
</li>
</ul>
<p>
Note that the usage of local storage is necessary for the proper functioning of the site, and it won't be disabled
if you choose to not grant cookie usage consent. This information is not used to track any user identifying
information. The data stored locally is only that required by the site to function.
</p>
<h3>How to control the cookies</h3>
<p>
You can change your cookie consent decision on Compiler Explorer by pressing one of the following buttons:
</p>
</body>
</html>

View File

@@ -0,0 +1,63 @@
// Be aware: modifying this file in any way will cause a pop-up to users telling them the cookie policy has changed.
html(lang="en")
body
span(id="last-changed")
| Last changed on:
|
time(id="changed-date" datetime=lastTime) #{lastTime}
|
| (
i
a(href="https://github.com/compiler-explorer/compiler-explorer/commit/#{lastCommit}" target="_blank") diff
| )
h2 Compiler Explorer Cookie Policy
p
| Browsers support the storing and sending back of small text files called "Cookies". These cookie files can be
| used (amongst other things) to help track the usage of a website. See
|
a(href="https://developer.mozilla.org/docs/Web/HTTP/Cookies"
target="_blank"
rel="noreferrer noopener") the Mozilla description of cookies
|
| for more details.
p
| Compiler Explorer uses Google Analytics, which in turn uses cookies. Google Analytics allows us to see how many
| individual users there are, how often users visit us, the average amount of time spent on the
| site, the frequency and distribution of compilers selected, and so on. It is invaluable in helping us make
| decisions in prioritising work on the site. It's important to note that these cookies are anonymous: we don't know
| who each individual user is. Our Google Analytics settings prevent data being retained for more than 14 months. The
| cookie stored is a first party cookie: you will find it in your browser under "godbolt.org" cookies.
p
| Your privacy is important to us, and you may opt out of this tracking at any time using the buttons on this dialog,
| with no loss of access or functionality of Compiler Explorer.
h2 #[span(style="color: darkslategray") Necessary] Local Storage
p
| To store your preferred options between sessions, such as your input code and user interface layout, we make use of
| your browser's local storage, where we place:
ul
li The current page state, such as:
ul
li Your current code
li Selected compilers and their options
li Pane layout
li Font sizes
li Your settings as shown in the settings popup (which can be found at: More > Settings), such as:
ul
li Your theme selection
li The default language
li Compile-as-you-type settings
p
| Note that the usage of local storage is necessary for the proper functioning of the site, and it won't be disabled
| if you choose to not grant cookie usage consent. This information is not used to track any user identifying
| information. The data stored locally is only that required by the site to function.
h3 How to control the cookies
p You can change your cookie consent decision on Compiler Explorer by pressing one of the following buttons:

View File

@@ -1,174 +0,0 @@
<!DOCTYPE html>
<!--
Be aware: modifying this file in any way will cause a pop-up to users telling them the privacy policy has changed.
-->
<html lang="en">
<body>
<!--
No need to update this! It's done by the build process.
-->
<span id="last-changed">
Last changed on: <time id="changed-date" datetime="{{lastTime}}">{{lastTime}}</time>
<i>
(<a href="https://github.com/compiler-explorer/compiler-explorer/commit/{{lastCommit}}" target="_blank">diff</a>)
</i>
</span>
<h2>Compiler Explorer Privacy Policy</h2>
<p>
Thanks for your interest in what Compiler Explorer does with your data. Data protection is really
important to the Compiler Explorer team, and we want to be very clear about what we do with your data.
</p>
<h3>Who we are</h3>
<p>
Compiler Explorer was created by and is primarily administrated by
<a href="mailto:matt@godbolt.org">Matt Godbolt</a>,
along with a number of volunteers (including, but not limited to those listed in our "<a
href="https://github.com/compiler-explorer/compiler-explorer/blob/main/AUTHORS.md" target="_blank"
rel="noreferrer noopener">Authors</a>" documentation).
It is run on a best-effort basis, and is not a commercial product. We do our best
to keep your data safe, but welcome help from the community: See our
<a href="https://github.com/compiler-explorer/compiler-explorer" target="_blank"
rel="noreferrer noopener">GitHub project page</a> if you wish to help.
</p>
<h3>Your data</h3>
<p>
In order to process compilation and execution requests, your browser sends the source code you typed in the editor
window along with your chosen compiler and options to the Compiler Explorer servers. There, the source code is
written to disk and your chosen compiler is invoked on it. If your request was to have your code executed, the
resulting executable is run. The outputs from compilation and execution are processed and sent back to your web
browser, where they're shown. Shortly after this process completes, your source code is deleted from disk. If, in
processing your query, an issue with Compiler Explorer is found, your code may be kept for up to a week in order to
help debug and diagnose the problem. Only the Compiler Explorer team will have access to your code, and only for the
purposes of debugging the site: we will never share your code with anyone.
</p>
<p>
If you choose a Microsoft compiler, then your code may be sent to and compiled on a machine administrated by
Microsoft. Such code is covered by the <a href="https://privacy.microsoft.com/en-US/" target="_blank">Microsoft
Privacy Policy.</a>
</p>
<p>
The source code and options are also subject to a one-way hash, which is used to cache the results to speed up
subsequent compilations of the same code. The cache is in-memory and on-disk. It's impossible to reconstruct the
source code from the hash, but the resulting assembly code or binary output (the compilation result) is stored as
plain text. There's no way to enumerate the in-memory cache contents. In exceptional cases, administrator members of
the Compiler Explorer team may be able to enumerate the disk caches and retrieve the compilation output, but with no
way to trace it back to the source code.
</p>
<p>
In short: your source code is stored in plaintext for the minimum time feasible to be able to process your request.
After that, it is discarded and is inaccessible. In very rare cases your code may be kept for a little longer (at
most a week) to help debug issues in Compiler Explorer.
</p>
<h4>Short links</h4>
<p>
If you choose to share your code using the "Share" dropdown, then the user interface state including the source code
is stored. For a "Full" link, this information is encoded into the URL as a URL hash (e.g.
<code>https://godbolt.org/#ui_state_and_code</code>). For short URLs, the interface state is stored on Compiler
Explorer's servers, and a shortened name uniquely referring to this data is returned. The shortened name comes from
a secure hash of the state, and without knowing the name it is infeasible to access the data. Only Compiler Explorer
administrators can access this data directly. Obfuscated IP addresses and creation time are stored alongside this
data, to enable spam detection. Links of this form look like <code>https://godbolt.org/z/SHORTNAME</code>.
</p>
<p>
Prior to storing data itself, Compiler Explorer used an external URL shortening service
(<a href="https://goo.gl/" target="_blank">goo.gl</a>) and the resulting short URL was rewritten as
<code>https://godbolt.org/g/SHORTURLPART</code>. The storage for the user experience state in this case remains with
the short URL provider, not Compiler Explorer.
</p>
<h4>Application, web and error logs</h4>
<p>
Compiler Explorer keeps application logs, which contain semi-anonymised IP addresses, but no other personally
identifying information. When a long URL is clicked, the hash part of the URL is not sent to the server, so the user
state (including the source code) is NOT exposed in the web log. If a user clicks a short URL, then the short form
IS exposed in the web log (as <code>https://godbolt.org/g/SHORTURLPART</code>) and from this the source code can be
retrieved. As such, if you create a short URL of your code, your source code and other user state can in principle
be retrieved from the web log of Compiler Explorer.
</p>
<p>
Compiler Explorer uses Amazon's web serving, load balancing and edge caching systems. In order to debug and diagnose
Compiler Explorer, to help track down and block Denial of Service attacks, and to gather statistics about Compiler
Explorer's performance and usage, the logs from these systems are archived. These logs contain the full IP addresses
of requests. They are kept for no more than one month, after which they are permanently deleted.
</p>
<p>
If your web browser experiences an error, we use a third party reporting system (<a
href="https://sentry.io/">Sentry</a>). This keeps information, including your IP address and web browser user
agent, for no more than 90 days.
</p>
<h4>Executing your code</h4>
<p>
For certain configurations, we may support executing the results of your compilation on the Compiler Explorer
servers. Execution occurs in a heavily locked-down, isolated environment. We have made reasonable efforts to protect
both the Compiler Explorer site and other concurrently-processed requests from information leakage due to rogue
executions.
</p>
<h4>Cookies</h4>
<p>
Separately, Compiler Explorer uses small pieces of information stored on your computer: Cookies and Browser Local
Storage. Cookies are only used with the user's permission, and are used with external analytics services (e.g.
Google Analytics) to gather statistics on Compiler Explorer usage. This information is used to help the Compiler
Explorer team plan for future updates and hardware upgrades in order to ensure the site remains stable and
responsive. Local storage is used to remember the user's settings, source code and user interface configuration, so
that it's available when the user visits the Compiler Explorer site again. This information is not transmitted to
Compiler Explorer, except as described above in order to fulfil the user's requests. There is a
<a href="#cookies" rel="noreferrer noopener">separate document</a> covering more on this. Statistics tracking
information is kept for 14 months, after which it is removed.
</p>
<h3>Your choices</h3>
<p>
Compiler Explorer is an open source project. If you are concerned about any of the data protection measures outlined
above, or about what happens to your source code, you are encouraged to run your own local instance of Compiler
Explorer. Instructions on how to do this are on the
<a href="https://github.com/compiler-explorer/compiler-explorer" target="_blank"
rel="noreferrer noopener">GitHub project page</a>.
</p>
<h3>Compiler Explorer and the GDPR</h3>
<p>
The Compiler Explorer team believes the Compiler Explorer site is compliant with the EU's General Data Protection
Regulation (GDPR). Specifically, we store no personally identifying information, we anonymise the little data that
we do have and we do not permanently store any user data.
</p>
<h4>Name and Address of the controller</h4>
<p>
The Controller for the purposes of the General Data Protection Regulation (GDPR), other data protection laws
applicable in Member states of the European Union and other provisions related to data protection is:
</p>
<div>
Matt Godbolt<br>
2626 Orrington Ave<br>
Evanston IL 60201 USA<br>
+1 312 792-7931<br>
<a href="mailto:matt@godbolt.org">matt@godbolt.org</a>
</div>
</body>
</html>

View File

@@ -0,0 +1,164 @@
//Be aware: modifying this file in any way will cause a pop-up to users telling them the privacy policy has changed.
html(lang="en")
body
span(id="last-changed")
| Last changed on:
|
time(id="changed-date" datetime=lastTime) #{lastTime}
|
| (
i
a(href="https://github.com/compiler-explorer/compiler-explorer/commit/#{lastCommit}" target="_blank") diff
| )
h2 Compiler Explorer Privacy Policy
p
| Thanks for your interest in what Compiler Explorer does with your data. Data protection is really
| important to the Compiler Explorer team, and we want to be very clear about what we do with your data.
h3 Who we are
p
| Compiler Explorer was created by and is primarily administrated by
|
a(href="mailto:matt@godbolt.org") Matt Godbolt
| , along with a number of volunteers (including, but not limited to those listed in our "
a(href="https://github.com/compiler-explorer/compiler-explorer/blob/main/AUTHORS.md"
target="_blank" rel="noreferrer noopener") Authors
| " documentation).
| It is run on a best-effort basis, and is not a commercial product. We do our best
| to keep your data safe, but welcome help from the community: See our
|
a(href="https://github.com/compiler-explorer/compiler-explorer"
target="_blank" rel="noreferrer noopener") GitHub project page
|
| if you wish to help.
h3 Your data
p
| In order to process compilation and execution requests, your browser sends the source code you typed in the editor
| window along with your chosen compiler and options to the Compiler Explorer servers. There, the source code is
| written to disk and your chosen compiler is invoked on it. If your request was to have your code executed, the
| resulting executable is run. The outputs from compilation and execution are processed and sent back to your web
| browser, where they're shown. Shortly after this process completes, your source code is deleted from disk. If, in
| processing your query, an issue with Compiler Explorer is found, your code may be kept for up to a week in order to
| help debug and diagnose the problem. Only the Compiler Explorer team will have access to your code, and only for the
| purposes of debugging the site: we will never share your code with anyone.
p
| If you choose a Microsoft compiler, then your code may be sent to and compiled on a machine administrated by
| Microsoft. Such code is covered by the
|
a(href="https://privacy.microsoft.com/en-US/privacy.pug" target="_blank") Microsoft Privacy Policy.
p
| The source code and options are also subject to a one-way hash, which is used to cache the results to speed up
| subsequent compilations of the same code. The cache is in-memory and on-disk. It's impossible to reconstruct the
| source code from the hash, but the resulting assembly code or binary output (the compilation result) is stored as
| plain text. There's no way to enumerate the in-memory cache contents. In exceptional cases, administrator members of
| the Compiler Explorer team may be able to enumerate the disk caches and retrieve the compilation output, but with no
| way to trace it back to the source code.
p
| In short: your source code is stored in plaintext for the minimum time feasible to be able to process your request.
| After that, it is discarded and is inaccessible. In very rare cases your code may be kept for a little longer (at
| most a week) to help debug issues in Compiler Explorer.
h4 Short links
p
| If you choose to share your code using the "Share" dropdown, then the user interface state including the source code
| is stored. For a "Full" link, this information is encoded into the URL as a URL hash (e.g.
| #[code https://godbolt.org/#ui_state_and_code]). For short URLs, the interface state is stored on
| Compiler Explorer's servers, and a shortened name uniquely
| referring to this data is returned. The shortened name comes from a secure hash of the state, and without
| knowing the name it is infeasible to access the data. Only Compiler Explorer administrators can access this data
| directly. Obfuscated IP addresses and creation time are stored alongside this data, to enable spam detection.
| Links of this form look like #[code https://godbolt.org/z/SHORTNAME].
p
| Prior to storing data itself, Compiler Explorer used an external URL shortening service (
a(href="https://goo.gl/" target="_blank") goo.gl
| ) and the resulting short URL was rewritten as #[code https://godbolt.org/g/SHORTURLPART].
| The storage for the user experience state in this case remains with the short URL provider,
| not Compiler Explorer.
h4 Application, web and error logs
p
| Compiler Explorer keeps application logs, which contain semi-anonymised IP addresses, but no other personally
| identifying information. When a long URL is clicked, the hash part of the URL is not sent to the server, so the user
| state (including the source code) is NOT exposed in the web log. If a user clicks a short URL, then the short form
| #[em is] exposed in the web log (as #[code https://godbolt.org/g/SHORTURLPART]) and from this the source code can be
| retrieved. As such, if you create a short URL of your code, your source
| code and other user state can in principle be retrieved from the web log of Compiler Explorer.
p
| Compiler Explorer uses Amazon's web serving, load balancing and edge caching systems. In order to debug and diagnose
| Compiler Explorer, to help track down and block Denial of Service attacks, and to gather statistics about Compiler
| Explorer's performance and usage, the logs from these systems are archived. These logs contain the full IP addresses
| of requests. They are kept for no more than one month, after which they are permanently deleted.
p
| If your web browser experiences an error, we use a third party reporting system (
a(href="https://sentry.io/" target="_blank") Sentry
| ). This keeps information, including your IP address and web browser user agent, for no more than 90 days.
h4 Executing your code
p
| For certain configurations, we may support executing the results of your compilation on the Compiler Explorer
| servers. Execution occurs in a heavily locked-down, isolated environment. We have made reasonable efforts to protect
| both the Compiler Explorer site and other concurrently-processed requests from information leakage due to rogue
| executions.
h4 Cookies
p
| Separately, Compiler Explorer uses small pieces of information stored on your computer: Cookies and Browser Local
| Storage. Cookies are only used with the user's permission, and are used with external analytics services (e.g.
| Google Analytics) to gather statistics on Compiler Explorer usage. This information is used to help the Compiler
| Explorer team plan for future updates and hardware upgrades in order to ensure the site remains stable and
| responsive. Local storage is used to remember the user's settings, source code and user interface configuration, so
| that it's available when the user visits the Compiler Explorer site again. This information is not transmitted to
| Compiler Explorer, except as described above in order to fulfil the user's requests. There is a
|
a(href="#cookies" rel="noreferrer noopener") separate document
|
| covering more on this. Statistics tracking information is kept for 14 months, after which it is removed.
h3 Your choices
p
| Compiler Explorer is an open source project. If you are concerned about any of the data protection measures outlined
| above, or about what happens to your source code, you are encouraged to run your own local instance of Compiler
| Explorer. Instructions on how to do this are on the
|
a(href="https://github.com/compiler-explorer/compiler-explorer"
target="_blank" rel="noreferrer noopener") GitHub project page
| .
h3 Compiler Explorer and the GDPR
p
| The Compiler Explorer team believes the Compiler Explorer site is compliant with the EU's General Data Protection
| Regulation (GDPR). Specifically, we store no personally identifying information, we anonymise the little data that
| we do have and we do not permanently store any user data.
h4 Name and Address of the controller
p
| The Controller for the purposes of the General Data Protection Regulation (GDPR), other data protection laws
| applicable in Member states of the European Union and other provisions related to data protection is:
div
| Matt Godbolt
br
| 2626 Orrington Ave
br
| Evanston IL 60201 USA
br
| +1 312 792-7931<br>
a(href="mailto:matt@godbolt.org") matt@godbolt.org

View File

@@ -69,6 +69,11 @@ var hasUIBeenReset = false;
var simpleCooks = new SimpleCook();
var historyWidget = new HistoryWidget();
var policyDocuments = {
cookies: require('./generated/cookies.pug').default,
privacy: require('./generated/privacy.pug').default,
};
function setupSettings(hub) {
var eventHub = hub.layout.eventHub;
var defaultSettings = {
@@ -111,7 +116,7 @@ function setupSettings(hub) {
}
function hasCookieConsented(options) {
return jsCookie.get(options.policies.cookies.key) === options.policies.cookies.hash;
return jsCookie.get(options.policies.cookies.key) === policyDocuments.cookies.hash;
}
function isMobileViewer() {
@@ -130,17 +135,18 @@ function setupButtons(options) {
// so we instead trigger a click here when we want it to open with this effect. Sorry!
if (options.policies.privacy.enabled) {
$('#privacy').on('click', function (event, data) {
$.get(window.location.origin + window.httpRoot + 'static/generated/privacy.html').done(function (policy) {
var modal = alertSystem.alert(data && data.title ? data.title : 'Privacy policy', policy);
calcLocaleChangedDate(modal);
// I can't remember why this check is here as it seems superfluous
if (options.policies.privacy.enabled) {
jsCookie.set(options.policies.privacy.key, options.policies.privacy.hash, {
expires: 365,
sameSite: 'strict',
});
}
});
var modal = alertSystem.alert(
data && data.title ? data.title : 'Privacy policy',
policyDocuments.privacy.text
);
calcLocaleChangedDate(modal);
// I can't remember why this check is here as it seems superfluous
if (options.policies.privacy.enabled) {
jsCookie.set(options.policies.privacy.key, policyDocuments.privacy.hash, {
expires: 365,
sameSite: 'strict',
});
}
});
}
@@ -155,19 +161,17 @@ function setupButtons(options) {
);
};
$('#cookies').on('click', function () {
$.get(window.location.origin + window.httpRoot + 'static/generated/cookies.html').done(function (cookies) {
var modal = alertSystem.ask(getCookieTitle(), cookies, {
yes: function () {
simpleCooks.callDoConsent.apply(simpleCooks);
},
yesHtml: 'Consent',
no: function () {
simpleCooks.callDontConsent.apply(simpleCooks);
},
noHtml: 'Do NOT consent',
});
calcLocaleChangedDate(modal);
var modal = alertSystem.ask(getCookieTitle(), policyDocuments.cookies.text, {
yes: function () {
simpleCooks.callDoConsent.apply(simpleCooks);
},
yesHtml: 'Consent',
no: function () {
simpleCooks.callDontConsent.apply(simpleCooks);
},
noHtml: 'Do NOT consent',
});
calcLocaleChangedDate(modal);
});
}
@@ -183,9 +187,7 @@ function setupButtons(options) {
});
$('#changes').on('click', function () {
$.get(window.location.origin + window.httpRoot + 'static/generated/changelog.html').done(function (changelog) {
alertSystem.alert('Changelog', $(changelog));
});
alertSystem.alert('Changelog', $(require('./generated/changelog.pug').default.text));
});
$('#ces').on('click', function () {
@@ -338,7 +340,7 @@ function initPolicies(options) {
$('#privacy').trigger('click', {
title: 'New Privacy Policy. Please take a moment to read it',
});
} else if (options.policies.privacy.hash !== jsCookie.get(options.policies.privacy.key)) {
} else if (policyDocuments.privacy.hash !== jsCookie.get(options.policies.privacy.key)) {
// When the user has already accepted the privacy, just show a pretty notification.
var ppolicyBellNotification = $('#policyBellNotification');
var pprivacyBellNotification = $('#privacyBellNotification');
@@ -355,7 +357,7 @@ function initPolicies(options) {
}
}
simpleCooks.setOnDoConsent(function () {
jsCookie.set(options.policies.cookies.key, options.policies.cookies.hash, {
jsCookie.set(options.policies.cookies.key, policyDocuments.cookies.hash, {
expires: 365,
sameSite: 'strict',
});
@@ -381,7 +383,7 @@ function initPolicies(options) {
// '' means no consent. Hash match means consent of old. Null means new user!
var storedCookieConsent = jsCookie.get(options.policies.cookies.key);
if (options.policies.cookies.enabled) {
if (storedCookieConsent !== '' && options.policies.cookies.hash !== storedCookieConsent) {
if (storedCookieConsent !== '' && policyDocuments.cookies.hash !== storedCookieConsent) {
simpleCooks.show();
var cpolicyBellNotification = $('#policyBellNotification');
var cprivacyBellNotification = $('#privacyBellNotification');

View File

@@ -22,14 +22,12 @@
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
import {execSync} from 'child_process';
import path from 'path';
import {fileURLToPath} from 'url';
/* eslint-disable node/no-unpublished-import */
import CopyWebpackPlugin from 'copy-webpack-plugin';
import CssMinimizerPlugin from 'css-minimizer-webpack-plugin';
import Handlebars from 'handlebars';
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
import MonacoEditorWebpackPlugin from 'monaco-editor-webpack-plugin';
import TerserPlugin from 'terser-webpack-plugin';
@@ -43,20 +41,6 @@ console.log(`webpack config for ${isDev ? 'development' : 'production'}.`);
const distPath = path.resolve(__dirname, 'out', 'dist');
const staticPath = path.resolve(__dirname, 'out', 'webpack', 'static');
function execGit(command) {
const gitResult = execSync(command);
if (!gitResult) {
throw new Error(`Failed to execute ${command}`);
}
return gitResult.toString();
}
const gitChanges = execGit('git log --date=local --after="3 months ago" "--grep=(#[0-9]*)" --oneline')
.split('\n')
.map(line => line.match(/(?<hash>\w+) (?<description>.*)/))
.filter(x => x)
.map(match => match.groups);
// Hack alert: due to a variety of issues, sometimes we need to change
// the name here. Mostly it's things like webpack changes that affect
// how minification is done, even though that's supposed not to matter.
@@ -98,19 +82,7 @@ const plugins = [
'window.PRODUCTION': JSON.stringify(!isDev),
}),
new CopyWebpackPlugin({
patterns: [
{from: './static/favicon.ico', to: path.resolve(distPath, 'static', 'favicon.ico')},
{
from: './static/generated/*.html',
to: path.resolve(distPath),
toType: 'dir',
transform: (content, filename) => {
const lastTime = execGit(`git log -1 --format=%cd "${filename}"`).trimEnd();
const lastCommit = execGit(`git log -1 --format=%h "${filename}"`).trimEnd();
return Handlebars.compile(content.toString())({gitChanges, lastTime, lastCommit});
},
},
],
patterns: [{from: './static/favicon.ico', to: path.resolve(distPath, 'static', 'favicon.ico')}],
}),
];
@@ -186,8 +158,8 @@ export default {
parser: {dataUrlCondition: {maxSize: 8192}},
},
{
test: /\.(html)$/,
loader: 'html-loader',
test: /.pug$/,
loader: './etc/scripts/parsed_pug_file.js',
},
{
test: /\.tsx?$/,